[你必须知道的.NET]第二十七回:interface到底继承于object吗?

说在,开篇之前
在.NET世界里,我们常常听到的一句话莫过于“System.Object是一切类型的根,是所有类型的父类”,以至于我在《你必须知道的.NET》8.1节 以“万物归宗:System.Object”这样的title为System.Object授予至高荣誉。所以,基于这样的观点就有了下面这句“接口是否也继承于System.Object?”,事实上这正是今天在技术群里小小讨论的一个插曲。  

                                                                                      www.anytao.com

 

 

 

1 缘起

在.NET世界里,我们常常听到的一句话莫过于“System.Object是一切类型的根,是所有类型的父类”,以至于我在《你必须知道的.NET》8.1节 以“万物归宗:System.Object”这样的title为System.Object授予至高荣誉。所以,基于这样的观点就有了下面这句“接口是否也继承于System.Object?”,事实上这正是今天在技术群里小小讨论的一个插曲。

持“interface也继承于object”,是基于以下的两个观点推断的:

观点一:

接口本质上也是一个class,因为接口类型编译之后在IL中被标识为.class,既然是类那么不可避免的最终继承于System.Object。

观点二:

假如有如下的接口和实现接口的类型:

// Release : code01, 2009/03/04                    
// Author  : Anytao, http://www.anytao.com
// List    : IObjectable.cs
public interface IObjectable
{
}
// Release : code02, 2009/03/04                    
// Author  : Anytao, http://www.anytao.com
// List    : MyObject.cs
public class MyObject : IObjectable
{
}
那么,对于IObjectable对象而言,下面的调用是可行的:
// Release : code03, 2009/03/04                    
// Author  : Anytao, http://www.anytao.com
// List    : Program.cs
class Program
{static void Main(string[] args){IObjectable obj = new MyObject();//Call Object instance methodsobj.ToString();//Call Object static methodsIObjectable.Equals(null, null);}
}

显然,IObjectable类型变量obj可以访问存在于System.Object中的实例方法ToString()和虚方法Equals,当然其他的几个公共服务也不例外:GetType()、Equals()、GetHashcode()、ReferenceEquals(),也可以由此推断interface可访问Object方法的蛛丝马迹。

不可否认,以上观点的部分推理是完全正确的,但是却遗憾的导致了错误的答案,所以在本文中我将明确的找出:interface不继承于object的原因和原理。关于接口本质话题的深度讨论,请参考《你必须知道的.NET》1.5 “玩转接口”和7.4 “面向抽象编程:接口和抽象类”的详细分析。

2 从面向对象寻找答案

为了找出接口继承的原因,我想从接口存在的意义入手是最能够说明问题的办法?接口,就像面向对象设计中的精灵,为OO思想注入了灵魂和活力,接口突破了继承在纵向上的扩展方向,在横向给予对象以更灵活的支持机制。

接口,封装了对于行为的抽象,定义了实现者必须遵守的契约。例如,实现了System.ICloneable接口的类型被赋予了“可以被拷贝”这样的契约,实现了System.Collections.IEnumerable接口的类型被赋予了“可以被枚举”这样的契约,不同的接口定义了不同的契约,就像不同的法律约束了不同的行为。那么接口应该赋予的契约至少在层次上保持相对的单纯和统一,如果为所有接口都无一例外的赋予GetType()、Equals()、GetHashcode()、ReferenceEquals()还有ToString()这样的契约,未免使得接口的纯洁和统一变得无从谈起,例如强迫任何实现了System.ICloneable接口的类型同时遵守其他的约定是对ICloneable本身的侮辱。

从接口单一原则延伸思考,一个包含杂七杂八的接口定义显然不是interface应该具有的纯正血统,对于深谙面向对象为何物的.NET设计者而言,这是不言而喻的问题。所以,我们从接口本身的职责和意义出发,决定interface不从System.Object继承是完全正确的。

3 在IL探求究竟

再次应用强大的IL武器来探求事实的真相,我们以Reflector打开所有的.NET既有接口,例如IList、IEmumerable、ICollection,都会有个共同的发现那就是你找不到extends System.Object这样的标识:

.class public interface abstract auto ansi ICloneable
{.custom instance void System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = { bool(true) }.method public hidebysig newslot abstract virtual instance object Clone() cil managed{}
}
自定义类型也是如此,我们看看IObjectable的IL反编译定义:
.class public interface abstract auto ansi IObjectable
{
}
而以extends标识继承关系是IL代码告诉我们真相的最佳证明。

System.Object真是“万物归宗”吗?

让我们再次回眸一笑,把Object进行一番把玩,难道一切类型都得继承自Object吗?其实不然。以ILASM.exe进行IL代码编译时,有一个参数选项NOAUTOINHERIT,正如其解释所描述的那样:

/NOAUTOINHERIT  Disable inheriting from System.Object by default

显然NoAutoInherit选项提供了为.NET类型“去掉帽子”的作用,简单言之就是,在未指定基类时,禁止类型自动从Object继承。

我们可以玩儿一个翻来覆去的IL游戏,将我们本文开始的Anytao.Insidenet.InterfaceInside.exe控制台程序以ILDASM.exe工具Dump为IL代码My.il,例如MyObject被反编译为:

.class public auto ansi beforefieldinit Anytao.Insidenet.InterfaceInside.MyObjectextends [mscorlib]System.Objectimplements Anytao.Insidenet.InterfaceInside.IObjectable
{.method public hidebysig specialname rtspecialname instance void  .ctor() cil managed{// Code size       7 (0x7).maxstack  8IL_0000:  ldarg.0IL_0001:  call       instance void [mscorlib]System.Object::.ctor()IL_0006:  ret} // end of method MyObject::.ctor} // end of class Anytao.Insidenet.InterfaceInside.MyObject

我们可以选择删除其中所有extends继承的代码,再以ILASM.exe对其进行noautoinherit编译,并生成

ilasm /exe /output:noobject.exe /noautoinherit my.il

新生成的noobject.exe程序将没有从object继承,某种程度上打破了“万物归宗”的创奇,MyObject就像一个无根之木,飘摇在我机器的某个深处。

4 结论

interface不从object继承,那么足下高见呢?文章虽短,取一瓢饮之,畅也。

那么,我们该如何回答本文开始对此质疑的两种观点呢?

回答观点一:

接口本质上还是一个类,但是一个特殊的类,它的特殊性表现在诸多的方面,例如所有的方法和属性都是抽象的、支持多继承等等,既然特殊那就特殊到底,不继承于任何的父类也是其中之一吧。

虽然这种解释未免牵强,但是如前文所述回到接口本源的角度而言,却是最好的解释。

回答观点二:

.NET一切类型都隐式继承于System.Object,那么对于实现了任何接口的类型而言,例如:

// Release : code02, 2009/03/04                    
// Author  : Anytao, http://www.anytao.com
// List    : MyObject.cs
public class MyObject : IObjectable
{
}

其在本质上相当于:

// Release : code02, 2009/03/04                    
// Author  : Anytao, http://www.anytao.com
// List    : MyObject.cs
public class MyObject : Object, IObjectable
{
}

所以对于MyObject实例obj而言,obj.ToString()实质是MyObject类继承于object,而不代表接口IObjectable也继承于object。那么IObjectable.Equals()则是编译器做了手脚,将IObjectable.Equals()翻译为Object.Equals()所致(来自脑袋高论,表示热烈感谢)。事实上,对于接口声明类型的方法调用,在实现机制上完全不同于一般的直接方法调用和虚方法分派机制,我们将在后续篇幅中详细讨论这一更重要的话题。

好了,interface,想说爱你不容易,可能我们还会再次相遇,也敬请朋友们继续关注:你必须知道的.NET。

 

补充讨论:Leo Zhang,Interface到底继承于Object吗?之我见

支持(0) 反对(0)

  

#8楼 2009-03-05 08:37 海天一鸥

CLR对象可以继承另一个对象,可以继承N多个接口。

所有的对象都有根继承对象Sytem.Object,但它可以继承多个接口。接口和对象仍然是本质上不同的东西。
 

支持(0) 反对(0)

  

#9楼 [楼主] 2009-03-05 08:53 Anytao

@xiao_p 
哈哈,老赵一般都比较晚,我很少这么晚,那是因为我没他那么牛,所以不敢晚睡:-)

支持(0) 反对(0)

  

#10楼 2009-03-05 08:55 落实

天呀,这么晚还不睡?牛人呀,我佩服!

支持(0) 反对(0)

  

#11楼 [楼主] 2009-03-05 08:56 Anytao

@·风信子· 
非也非也,我在博客上所发表的只有全书内容的20%左右,所以大部分精彩的内容还得到书上寻找答案。 

从第20回起发表的系列文章,在书中并未包括,我将其戏称为“必须的2.0”,这些新内容将考虑在后续《你必须知道的.NET》中出版。 

谢谢:-)

支持(0) 反对(0)

  

#12楼 [楼主] 2009-03-05 08:57 Anytao

@李战 
老哥,近来很少见你冒泡了,常来呀:-P

支持(0) 反对(0)

  

#13楼 [楼主] 2009-03-05 08:57 Anytao

@CoderZh 
--引用-------------------------------------------------- 
CoderZh: 刚到公司,惯例先浏览博客园的新文章。 
-------------------------------------------------------- 
好像是很多人的习惯

支持(0) 反对(0)

  

#14楼 [楼主] 2009-03-05 09:00 Anytao

@海天一鸥 
诚如所言,接口确实存在诸多的不一样,本文论述的也算是特殊之一,但是在IL级别将接口看做class也未尝不可。

支持(0) 反对(0)

  

#15楼 [楼主] 2009-03-05 09:01 Anytao

@落实 
一口气上五楼,不觉得累:-) 

写完才发现,好像比较晚了,好在时间没有太久:-)

支持(0) 反对(0)

  

#16楼 [楼主] 2009-03-05 09:03 Anytao

@Anders Liu 
哈哈,是滴是滴,这也算“罪证”之一。

支持(0) 反对(0)

  

#17楼 2009-03-05 09:07 不知道用什么昵称了

先留名在读 
一天睡几个小时呀,佩服

支持(0) 反对(0)

  

#18楼 2009-03-05 09:08 Jeffrey Zhao

有时候也很矛盾啊,比如: 
IMyObject o = ... 
Type t = o.GetType(); 

如果我说,如果IMyObject没有定义GetType方法的话,为什么可以这样调用呢?我觉得从概念上,语言已经作了约定了,即任何对象都会继承Object,拥有Object的成员。 
那么,如果/noautoinherit了呢?我不知道啊,如果没人试试看的话只能我自己来了,赫赫…… 

支持(0) 反对(0)

  

#19楼 2009-03-05 09:14 徐少侠

我的理解是编译器做的手脚

同样的问题还出现在值类型、枚举这些东西身上

从定义上说,他们也都是派生自object的
 

支持(0) 反对(0)

  

#20楼 [楼主] 2009-03-05 09:14 Anytao

@-brian- 
今天睡的比较少

支持(0) 反对(0)

  

#21楼 2009-03-05 09:17 麒麟.NET

@李战 
呵呵,我通常是一边吃早饭一边看 

//如果留言有表情,好像无法引用,是个bug吧?

支持(0) 反对(0)

  

#22楼 2009-03-05 09:18 飞林沙

@Jeffrey Zhao 

那么,如果/noautoinherit了呢?我不知道啊,如果没人试试看的话只能我自己来了,赫赫…… 
----------------- 
如果那样的话,一样可以调用GetType()方法的。我还是支持观点一,我一直都坚信,接口从本质上来说,是一个类。不过是一个特殊的类罢了

支持(0) 反对(0)

  

#23楼 2009-03-05 09:18 WXWinter(冬)

接口,是栈模板 
类(这里指类的实体部分),是堆模板 

如果有如下结构: 
//======== 
public interface I 

void call(); 


public class C1 : I 


public void call() 




//======= 
当我们这样写时: 
C1 obj = new C1(); 
其实是完成了如下工作: 
I obj = new C1(); 

(1) I obj : 用接口初始化栈 
(2) new C1() : 用类实体初始化堆 
(3) = : 栈与堆关联 

//========== 
当然,很多时候我们常这样写 

public class C2 

public void call() 




//- 
C1 obj = new C1(); 

其实通常情况下,定义一个类,一定要有接口与实现两部份,只不过很多语言帮我们做了这样一件事,当定义一 

Class时,如果有的实现不是实现某个接口的定义,在使用时会为其提取一个接口,用于初始化栈 


接口,存在于栈中 
类(这里指类的实体部分),存在于堆中, 
他们分别处于两个世界中,沟通这两个世界的纽带就是指针. 

而NET中的interface与Class只不过是对这个基本关系进行了一个包装

支持(0) 反对(0)

  

#24楼 [楼主] 2009-03-05 09:19 Anytao

@Jeffrey Zhao 
-------------------------- 
IMyObject o = new LaoZhao(); 
Type t = o.GetType(); 
-------------------------- 
哈哈,这一点不奇怪,因为为o实例化的类型(例如LaoZhao)同时隐式继承于object,所以以o访问GetType是没有任何问题的,而且返回的应该是类型LaoZhao。 

关于/noautoinherit情况,试完告诉我:-) 

 

支持(0) 反对(0)

  

#25楼 2009-03-05 09:20 红泥

interface A
{
void Do();
}

class B : A
{
public void Do() { }
}

class Test
{
static void Main()
{
A a = new B();
a.ToString();
A.Equals(null,null);
Console.Read();
}
}
a.ToString();A.Equals(null,null);能调用都是为了圆‘一切继承自Object’吧,即使接口不继承自Object,也能做成像继承Object(其实把A.Equals(null,null)编译成call bool [mscorlib]System.Object::Equals(object,object))

但下面就有些迷惑了:
!dumpclass 009813b8
Class Name: A
mdToken: 02000002 (C:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\ph\ph\bin\Debug\ph.exe)
Parent Class: 790c3ef0
Module: 00982c5c
Method Table: 00983094
Vtable Slots: 1
Total Method Slots: 1
Class Attributes: a0 Interface, Abstract, 
NumInstanceFields: 0
NumStaticFields: 0

!dumpclass 790c3ef0
Class Name: System.Object
mdToken: 02000002 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Parent Class: 00000000
Module: 790c1000
Method Table: 79330508
Vtable Slots: 4
Total Method Slots: a
Class Attributes: 102001 
NumInstanceFields: 0
NumStaticFields: 0

能看出来A的父类Parent Class: 790c3ef0是Object,这个是为啥,也是为了圆’一切都继承Object'?
呵呵

支持(0) 反对(0)

  

#26楼 2009-03-05 09:21 Jeffrey Zhao

@Anytao 
但是接口引用的对象,应该只能访问到接口的成员吧,从概念上讲。 
编译器在这方面就是在搞“默认”了。

支持(0) 反对(0)

  

#27楼 [楼主] 2009-03-05 09:22 Anytao

@徐少侠 
编译器将将IObjectable.Equals()翻译为Object.Equals(),是编译器做的小小手脚,而IObjectable是否继承于Object,则是“与生俱来”的。

支持(0) 反对(0)

  

#28楼 2009-03-05 09:22 dfgdfgdfgdfgd

用户自定义类型默认是继承object的,只不过编译器隐式的为我们写好了。

第二点 就是刚刚提到的 interface 不继承object 可不可以认为 interface 和object 都是用户类型的基类 .而唯一的区别在于object 提供几个方法让子类去实现。

支持(0) 反对(0)

  

#29楼 [楼主] 2009-03-05 09:24 Anytao

@麒麟.NET 
可以通知dudu,help了

支持(0) 反对(0)

  

#30楼 2009-03-05 09:25 小军人

写的比较易懂,看好你出《你必须知道的.NET》续. 

支持(0) 反对(0)

  

#31楼 [楼主] 2009-03-05 09:26 Anytao

@飞林沙 
--引用-------------------------------------------------- 
飞林沙: @Jeffrey Zhao 

那么,如果/noautoinherit了呢?我不知道啊,如果没人试试看的话只能我自己来了,赫赫…… 
----------------- 
如果那样的话,一样可以调用GetType()方法的。我还是支持观点一,我一直都坚信,接口从本质上来说,是一个类。不过是一个特殊的类罢了 
-------------------------------------------------------- 
我想文中已经有明确的解释和说明了

支持(0) 反对(0)

  

#32楼 2009-03-05 09:27 Jeffrey Zhao

--引用-------------------------------------------------- 
飞林沙: @Jeffrey Zhao 

那么,如果/noautoinherit了呢?我不知道啊,如果没人试试看的话只能我自己来了,赫赫…… 
----------------- 
如果那样的话,一样可以调用GetType()方法的。我还是支持观点一,我一直都坚信,接口从本质上来说,是一个类。不过是一个特殊的类罢了 
-------------------------------------------------------- 
那就怪了,如果noautoinherit,则说明类不默认继承Object,那么GetType()从哪里来?

支持(0) 反对(0)

  

#33楼 [楼主] 2009-03-05 09:30 Anytao

@WXWinter(冬) 
说得很精彩,不过是很多“障眼法”迷失了眼睛罢了。

支持(0) 反对(0)

  

#34楼 2009-03-05 09:34 dfgdfgdfgdfgd

--引用--------------------------------------------------
Jeffrey Zhao: --引用--------------------------------------------------
飞林沙: @Jeffrey Zhao

那么,如果/noautoinherit了呢?我不知道啊,如果没人试试看的话只能我自己来了,赫赫…… 
-----------------
如果那样的话,一样可以调用GetType()方法的。我还是支持观点一,我一直都坚信,接口从本质上来说,是一个类。不过是一个特殊的类罢了
--------------------------------------------------------
那就怪了,如果noautoinherit,则说明类不默认继承Object,那么GetType()从哪里来?
----------------------------------------------------------引用--------------------------------------------------
Jeffrey Zhao: --引用--------------------------------------------------
飞林沙: @Jeffrey Zhao

那么,如果/noautoinherit了呢?我不知道啊,如果没人试试看的话只能我自己来了,赫赫…… 
-----------------
如果那样的话,一样可以调用GetType()方法的。我还是支持观点一,我一直都坚信,接口从本质上来说,是一个类。不过是一个特殊的类罢了
--------------------------------------------------------
那就怪了,如果noautoinherit,则说明类不默认继承Object,那么GetType()从哪里来?
--------------------------------------------------------
应该还是从object 来

支持(0) 反对(0)

  

#35楼 2009-03-05 09:38 Jeffrey Zhao

@BZZ 
好吧,看上去大家还是在猜……过一会儿我自己去试试看

支持(0) 反对(0)

  

#36楼 2009-03-05 09:50 麒麟.NET

是不是也可以这样说,如果interface继承自Object,就无法实现多重继承了?

支持(0) 反对(0)

  

#37楼 [楼主] 2009-03-05 09:51 Anytao

@红泥 
需要一点探索和思考~~~

支持(0) 反对(0)

  

#38楼 [楼主] 2009-03-05 09:52 Anytao

@BZZ 
--引用-------------------------------------------------- 
BZZ: 用户自定义类型默认是继承object的,只不过编译器隐式的为我们写好了。 

第二点 就是刚刚提到的 interface 不继承object 可不可以认为 interface 和object 都是用户类型的基类 .而唯一的区别在于object 提供几个方法让子类去实现。 
-------------------------------------------------------- 
呵呵,这种说法我不敢贸然肯定,任何官方或者非官方都没有这么说过:-)

支持(0) 反对(0)

  

#39楼 [楼主] 2009-03-05 09:52 Anytao

@凌军 
谢谢

支持(0) 反对(0)

  

#40楼 2009-03-05 10:16 重典

@Jeffrey Zhao
老赵山寨我。。。。

支持(0) 反对(0)

  

#41楼 2009-03-05 10:25 我的地盘我做主

IObjectable obj = new MyObject(); 

//Call Object instance methods 
obj.ToString(); 


虽然MyObject也继承Object,由于obj的类型是IObjectable类型,所以在这里怎么能调用ToString()方法呢. 
看完了整片文章,对这里还是新潮疑惑

支持(0) 反对(0)

  

#42楼 2009-03-05 10:44 viping

从运行的情况看 
MyObject的Parent Class: 是System.Object,obj 可当做指针,在C#里它运行时是确定的(在C++里不确定,这就是CLR能使用GC的好处) 

但是如果把接口更改为: 
public abstract class IObjectable 
这样在运行时,MyObject的Parent Class是IObjectable,且Class Attributes: 为Abstract,。 
而IObjectable的Parent Class才是System.Object。 

所以接口这玩意规约于设计时。。与运行时无关。

支持(0) 反对(0)

  

#43楼 2009-03-05 10:57 jason wei

强解

支持(0) 反对(0)

  

#44楼 2009-03-05 10:58 残香恨

接口是不是可以看成这样的一个特殊“类”(在IL中,接口貌似类),它不仅有自己声明的方法,而且还把Object的所有方法声明“偷”过来了呢,因为任何implement接口的类,都直接或间接的extends了Object类。

支持(0) 反对(0)

  

#45楼 2009-03-05 12:04 会长

好文啊

支持(0) 反对(0)

  

#46楼 2009-03-05 13:04 AlexLiu

确实,我们似乎是应该对一些看似真理的东西,加以反思。 
凡事都要问一个为什么呢?

支持(0) 反对(0)

  

#47楼 2009-03-05 13:55 包建强

由于接口是由暴露给其它类型的项(方法、属性、事件)组成的描述符,所以接口本身不能提供这些项的实现,因此从定义上,它是一个抽象类型。在ILAsm中定义一个接口时,因为IL汇编器在遇到interface时会自动添加关键字abstract,所以可以省略关键字abstract。 
再说一个BT的概念,接口只可能为它的静态方法提供实现。就是说,在IL中,你可以写静态方法。我想,我这么说会雷倒一片人。

支持(0) 反对(0)

  

#48楼 [楼主] 2009-03-05 14:27 Anytao

@重典 
怎么山寨的,我也想:-P

支持(0) 反对(0)

  

#49楼 [楼主] 2009-03-05 14:28 Anytao

@我的地盘我做主 
呵呵,对于你提出的问题,需要一大篇长篇大论来解释,我已经计划在后续内容中,以3-4篇的内容来阐释清楚这个问题,届时再请来兄继续欣赏,何如?

支持(0) 反对(0)

  

#50楼 [楼主] 2009-03-05 14:31 Anytao

@红泥 
@overred
我想这是对运行时分析的很好的补充:-P

#55楼 [楼主] 2009-03-05 14:36 Anytao

@包建强 
好像谁也没雷着,详细参考:《Expert .NET 2.0 IL Assembler》 第七章 命名空间和类 

:-)

支持(0) 反对(0)

  

#56楼 2009-03-05 15:08 MSFT:waywa 韦恩卑鄙

--引用-------------------------------------------------- 
包建强: 由于接口是由暴露给其它类型的项(方法、属性、事件)组成的描述符,所以接口本身不能提供这些项的实现,因此从定义上,它是一个抽象类型。在ILAsm中定义一个接口时,因为IL汇编器在遇到interface时会自动添加关键字abstract,所以可以省略关键字abstract。 
再说一个BT的概念,接口只可能为它的静态方法提供实现。就是说,在IL中,你可以写静态方法。我想,我这么说会雷倒一片人。 
-------------------------------------------------------- 
我已经雷倒了

支持(0) 反对(0)

  

#57楼 2009-03-05 15:09 MSFT:waywa 韦恩卑鄙

--引用-------------------------------------------------- 
Anytao: @包建强 
好像谁也没雷着,详细参考:《Expert .NET 2.0 IL Assembler》 第七章 命名空间和类 

:-) 
-------------------------------------------------------- 
你骂我不是人 我bs你 亩哈哈

支持(0) 反对(0)

  

#58楼 2009-03-05 15:15 MSFT:waywa 韦恩卑鄙

个人认为 既然是共性的oo思想 那么 .net il 对于interface 的特殊处理就不应该作为共性的接口认知的一部分。初学者看了这篇文章 对理解.net 以外的接口会产生很不好的作用。 

作为正统oo思想 接口不能独立于实例存在 而且理应不存在任何已经实现的方法和静态成员,接口的实例不应存在,接口的静态方法也不应该存在 

在这个帖子里我不小心听到了一些关于,net的风言风语 现在我决定把它忘记。 

亩哈哈

支持(0) 反对(0)

  

#59楼 2009-03-05 15:40 Ivony...

这个题目本来就是不成立的,因为在C#的概念中,接口不是类,接口不能被继承(只能被实现),接口也不能从一个类型继承。而C#的官方说法也是,所有类型都间接继承于System.Object,这里的主语是类型,而不是接口。 

一个接口可以扩展(进化)另一个接口,但没有继承于某一个类型的概念。 



所以这个问题的答案应该说,“接口” “不能” “继承”,这个命题不成立。

支持(0) 反对(0)

  

#60楼 2009-03-05 16:00 我的地盘我做主

@Anytao 
呵呵,到时候我一定好好拜读你的佳作

支持(0) 反对(0)

  

#61楼 2009-03-05 17:55 Anders06

妙文妙文! 

接口定义可以理解为声明性的东西, 接口是不能直接被创建的,如下实际是创建了MyObject类的一个实例: 
IObjectable obj = new MyObject(); 

所以万物还是皆对象,不知是否可以如此理解

支持(0) 反对(0)

  

#62楼 2009-03-05 18:37 primeli

万物归宗System.Object。但Interface不是“物”,是契约,是规则,是虚的思想,不是实实在在的"物“。类似万有引力定律一样,是抽象出来的思想,不能归为物体。
OK,IObjectable obj = new MyObject(); 其实是实例化了一个继承自System.Object的具体对象,为啥?因为你用的是class MyObject。class关键字就表明了其肯定继承System.Object,是个实物。
而继承自IObjectable接口,仅仅是符合其契约和规则,符合协定的定律而已。照规矩办事,但规矩本身不是物,是抽象思维。
另外,interface关键字与class关键字代表的含义不同哦!你用class,默认继承System.Object。而用interface,你找不到System.Object痕迹。
因此,这个结论很简单:interface本身不继承System.Object,但其具体的实现(因为使用class关键字)肯定继承System.Object,也就是楼主的结论2。
大家想想:数学定律,万有引力定律等等能算“物”么?还是这些是客观存在的但没有任务物体附属的规律呢?

支持(0) 反对(0)

  

#63楼 2009-03-05 20:10 Anders06

@非主流程序员 

支持(0) 反对(0)

  

#64楼 [楼主] 2009-03-05 20:55 Anytao

@韦恩卑鄙 
呵呵,我是在你之前说的,再说包子雷人是他的事儿,反正我没被雷:-) 

不过,我作证你是大大的好人。

支持(0) 反对(0)

  

#65楼 [楼主] 2009-03-05 20:58 Anytao

@韦恩卑鄙 

--引用-------------------------------------------------- 
韦恩卑鄙: 个人认为 既然是共性的oo思想 那么 .net il 对于interface 的特殊处理就不应该作为共性的接口认知的一部分。初学者看了这篇文章 对理解.net 以外的接口会产生很不好的作用。 

作为正统oo思想 接口不能独立于实例存在 而且理应不存在任何已经实现的方法和静态成员,接口的实例不应存在,接口的静态方法也不应该存在 

在这个帖子里我不小心听到了一些关于,net的风言风语 现在我决定把它忘记。 

亩哈哈 
-------------------------------------------------------- 


事实上,对应接口不光是在IL层有特别的处理,其本质的定位上就是完全不同于普通类型的概念,所以对初学者有不好影响完全么必要,只要仔细看文章我想理解是很清楚的。 

另外,哪里有对.NET的风言风语呀:-)

支持(0) 反对(0)

  

#66楼 [楼主] 2009-03-05 21:30 Anytao

@Ivony... 
首先这不是一个关于C#接口和类概念的清算贴,全文没有任何字眼和概念直言接口就是类,类也是接口,如果那样搞两个概念是完全没有必要的,而且事实上我们讨论的是基于.NET概念而言,阐述的也是通用类型系统的概念。 

如果对于“而C#的官方说法也是,所有类型都间接继承于System.Object,这里的主语是类型,而不是接口。 ”有所质疑。那么,首先需要了解接口是不是类型,我想官方定义可能更加权威,所以请不妨参照:http://msdn.microsoft.com/zh-cn/library/2hf02550(VS.80).aspx 

事实上,对于类型的分类和定位,可以有多个角度,其实在我看来CTS单纯以值类型和引用类型的二元分法有时不一定表达了最科学的角度,例如从大概念上分为值类型、引用类型、指针类型和接口类型也未尝不可。 

本文的意义在于什么呢?我想答案是,事实上很多身边的朋友都存在对这一问题的误区,也是我想写写想法的初衷,仅此而已。 
 

支持(0) 反对(0)

  

#67楼 [楼主] 2009-03-05 21:30 Anytao

@我的地盘我做主 
谢谢

支持(0) 反对(0)

  

#68楼 [楼主] 2009-03-05 21:31 Anytao

@Anders06 
我觉得,可以这么理解,而且很对。哈哈

支持(0) 反对(0)

  

#69楼 [楼主] 2009-03-05 21:32 Anytao

@非主流程序员 
@Anders06 
表达同样的呼声:赞。

支持(0) 反对(0)

  

#70楼 2009-03-06 01:00 Anders Cui

嗯,唯“物”主义还是站得住脚的:)

支持(0) 反对(0)

  

#71楼 2009-03-06 09:34 MSFT:waywa 韦恩卑鄙

--引用-------------------------------------------------- 
Anytao: @韦恩卑鄙 

--引用-------------------------------------------------- 
韦恩卑鄙: 个人认为 既然是共性的oo思想 那么 .net il 对于interface 的特殊处理就不应该作为共性的接口认知的一部分。初学者看了这篇文章 对理解.net 以外的接口会产生很不好的作用。 

作为正统oo思想 接口不能独立于实例存在 而且理应不存在任何已经实现的方法和静态成员,接口的实例不应存在,接口的静态方法也不应该存在 

在这个帖子里我不小心听到了一些关于,net的风言风语 现在我决定把它忘记。 

亩哈哈 
-------------------------------------------------------- 


事实上,对应接口不光是在IL层有特别的处理,其本质的定位上就是完全不同于普通类型的概念,所以对初学者有不好影响完全么必要,只要仔细看文章我想理解是很清楚的。 

另外,哪里有对.NET的风言风语呀:-) 
-------------------------------------------------------- 

老包不是说interface 在il可以加入静态成员么 这么雷人的事情我尽量忘记他 恩恩 
 

支持(0) 反对(0)

  

#72楼 [楼主] 2009-03-06 09:54 Anytao

@Anders Cui 
:-)

支持(0) 反对(0)

  

#73楼 [楼主] 2009-03-06 10:15 Anytao

@韦恩卑鄙 
:-)

支持(0) 反对(0)

  

#74楼 2009-03-09 11:08 Ivony...

--引用-------------------------------------------------- 
Anytao: @Ivony... 

首先这不是一个关于C#接口和类概念的清算贴,全文没有任何字眼和概念直言接口就是类,类也是接口,如果那样搞两个概念是完全没有必要的,而且事实上我们讨论的是基于.NET概念而言,阐述的也是通用类型系统的概念。 



如果对于“而C#的官方说法也是,所有类型都间接继承于System.Object,这里的主语是类型,而不是接口。 ”有所质疑。那么,首先需要了解接口是不是类型,我想官方定义可能更加权威,所以请不妨参照:<a href="http://msdn.microsoft.com/zh-cn/library/2hf02550" target="_new">http://msdn.microsoft.com/zh-cn/library/2hf02550</a>(VS.80).aspx 



事实上,对于类型的分类和定位,可以有多个角度,其实在我看来CTS单纯以值类型和引用类型的二元分法有时不一定表达了最科学的角度,例如从大概念上分为值类型、引用类型、指针类型和接口类型也未尝不可。 



本文的意义在于什么呢?我想答案是,事实上很多身边的朋友都存在对这一问题的误区,也是我想写写想法的初衷,仅此而已。 




-------------------------------------------------------- 


事实上LZ已经在不知不觉中把这个问题给挖出来了,我只是进一步阐述罢了。 

我们证明一个命题之前,必须先将其中的概念明确。而在这个例子中,事实上继承这个概念就是不明确的,所以这个命题是没有意义的。 

这一点LZ已经在文章中挖出来了,只是自己没发现,引用文中一句话: 

“而以extends标识继承关系是IL代码告诉我们真相的最佳证明。” 


很好,如果我们定义extends标识了继承关系,那么继承接口是不是extends标识的呢?答案是否定的。 

这就出问题了,LZ在文中给我们提出了一个命题: 

“继承关系以extends标识“ 


如果这个命题是正确的,则接口永远不会出现在任何extends中,也不会extends任何别的东西(即使是“继承”于别的接口)。可以推论接口不能被任何东西“继承”也不能“继承”于任何东西。原命题“interface到底继承于object吗“就不成立了。 

如果这个命题是错误的,那么LZ的推论也就不成立了。 


所以要说明白“interface到底继承于object吗”,我们就一定要先厘清继承的定义。 

所以这个问题可以有N个答案,比如说: 


1、令“继承”即是指A类型对象可以直接被当作B类型对象处理,其中并无隐式类型转换,也未曾创建一个新的B类型的对象,而是用B类型来操作A类型对象,即称为A类型继承于B类型。 

从这个定义出发,接口的确继承于System.Object。就算实际上是实现接口的类型都继承于System.Object,但如果继承的定义仅从效果上来看待的话,那么接口的确继承于System.Object。 


其他的定义我就不探讨了。

支持(0) 反对(0)

  

#75楼 2009-03-31 23:15 残香恨

《框架设计(第二版):CLR Via C#》的P265-266:“此外,CLR还允许调用Object定义的方法,因为所有类都继承了Object的方法........此外,可以调用Object定义的任何一个方法(比如GetType),因为CLR知道所有类型都继承自Object。” 

由此可知,之所以出现这种现象,是CLR的支持,C#的约定。

支持(0) 反对(0)

  

#76楼 2009-05-22 16:12 DiggingDeeply

C++里没有interface关键字,但同样完美实现了OO,而且有多继承。 
叫什么无所谓,我的理解其实interface就是C++的抽象类的一种特例。 
可以这么理解,抽象类可以实现接口的功能,但是反之不行,因为接口不能有实现代码,所以接口也其实就是只含有定义的抽象类。 
不知道这么说合适不?

支持(0) 反对(0)

  

#77楼 2009-06-02 18:16 xxxxxxxxxxxxxxxxx

--引用--------------------------------------------------
我的地盘我做主: IObjectable obj = new MyObject();

//Call Object instance methods
obj.ToString();


虽然MyObject也继承Object,由于obj的类型是IObjectable类型,所以在这里怎么能调用ToString()方法呢.
看完了整片文章,对这里还是新潮疑惑
--------------------------------------------------------
这个时候,obj的类型并不是IObjectable,而是MyObject,IObjectable写在前面只是代表obj是一个实现了这个接口的类的实例。接口是不能实例化的。

支持(0) 反对(0)

  

#78楼 2009-06-02 18:24 xxxxxxxxxxxxxxxxx

--引用--------------------------------------------------
DiggingDeeply: C++里没有interface关键字,但同样完美实现了OO,而且有多继承。
叫什么无所谓,我的理解其实interface就是C++的抽象类的一种特例。
可以这么理解,抽象类可以实现接口的功能,但是反之不行,因为接口不能有实现代码,所以接口也其实就是只含有定义的抽象类。
不知道这么说合适不?
--------------------------------------------------------
支持你这种说法

支持(0) 反对(0)

  

#79楼 2009-08-21 03:11 拓荒者.贾

继承就是extends,实现就是implements.
继承就是继承,实现就是实现,索性清楚一点多好吗
直接搬用java代码,嘿嘿

 

支持(0) 反对(0)

  

#80楼 2011-10-14 14:08 杨曹贵

距离你出书已经有两年了,现在才来看你文章!会努力的学习,楼主V5.

支持(0) 反对(0)

  

#81楼 2015-03-07 21:48 残香恨

多年以后,回头来看,或许,这三行代码可以说明问题。
Type type = typeof(IDisposable);
Console.WriteLine(type.BaseType);
Console.WriteLine(type.IsSubclassOf(typeof(Object)));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438702.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机电子电路原理图,学看电路原理图入门知识积累 - 全文

一、电子电路的意义电路图是人们为了研究和工程的需要&#xff0c;用约定的符号绘制的一种表示电路结构的图形。通过电路图可以知道实际电路的情况。这样&#xff0c;我们在分析电路时&#xff0c;就不必把实物翻来覆去地琢磨&#xff0c;而只要拿着一张图纸就可以了。在设计电…

hrsc2016 下载 数据集_PIoU Loss:倾斜目标检测专用损失函数,公开超难倾斜目标数据集Retail50K | ECCV 2020 Spotlight...

> 论文提出从IoU指标延伸来的PIoU损失函数&#xff0c;能够有效地提高倾斜目标检测场景下的旋转角度预测和IoU效果&#xff0c;对anchor-based方法和anchor-free方法均适用。另外论文提供了Retail50K数据集&#xff0c;能够很好地用于评估倾斜目标检测算法的性能来源&#x…

[你必须知道的.NET]第二十八回:说说Name这回事儿

1 缘起 老赵在谈表达式树的缓存&#xff08;2&#xff09;&#xff1a;由表达式树生成字符串中提到&#xff0c;在描述Type信息时讨论FullName或者AssemblyQualifiedName提供完整的Type信息&#xff0c;虽是小话题&#xff0c;但却是值得有聊的话题。在.NET中反应一个Type名称…

2017计算机三级试卷,2017年计算机三级《网络技术》测试题及答案

2017年计算机三级《网络技术》测试题及答案参考答案及解析1.B【解析】密集波分复用(DenseWave1engthDivisionMu1tip1exin9&#xff0c;DWDM)技术&#xff0c;指的是一种光纤数据传输技术&#xff0c;这一技术利用激光的波长按照比特位并行传输或者字符串行传输方式在光纤内传递…

library的英语怎么读音_【英语角】———学习方法分享

点击蓝字 关注我们每天学习一点点单词的记忆是一件很让人头疼的事情&#xff0c;但单词又是学习英语的基石&#xff0c;非常重要。那么有什么方法能让单词记忆变得简单有效呢&#xff1f;不妨试试下面这些方法吧。1、卡片记忆自制单词卡片&#xff0c;随身带着&#xff0c;有空…

计算机作文叙事,电脑争夺战叙事作文

电脑争夺战叙事作文在生活、工作和学习中&#xff0c;大家一定都接触过作文吧&#xff0c;作文是通过文字来表达一个主题意义的记叙方法。那么你有了解过作文吗&#xff1f;下面是小编帮大家整理的电脑争夺战叙事作文&#xff0c;欢迎阅读与收藏。这是一个温暖的下午&#xff0…

[你必须知道的.NET]第二十九回:.NET十年(上)

引言 语言是程序开发者行走江湖的手上利器&#xff0c;各大门派的高手在论坛、博客为了自家门派争吵不已早是技术世界中的亮丽风景&#xff0c;虽多少为刚刚踏入江湖的新手提供了思考的素材&#xff0c;但也同时迷惑了初出茅庐的前行方向。 本文不欲计较门派的高下&#xff0…

springboot 做表白墙_华广表白墙 第六期|hsl每天都想和你嘻嘻哈哈

1回复第五期 10 没了就没了&#xff0c;不值得就要留恋219级人力4班的银发女生看见你的第一眼就觉得你是一个天使&#xff0c;你的眼睛真的把我迷住了。如果可以的话能不能加你的微信&#xff0c;谢谢?3捞一下13号(周日晚上)21.15左右在校门口益禾堂买奶茶的小姐姐 金发 牛仔…

51系列计算机字长,计算机等级考试之MsOffice练习题第51套

为了让广大各位考生更好的复习&#xff0c;帮考网小编整理提供了2012计算机等级考试一级MsOffice精选题(51)&#xff0c;以供各位考生复习参考&#xff0c;希望对考生复习有所帮助。/计算机二级2012计算机等级考试一级MsOffice精选题(51)1)。 正确的IP地址是A) 202.112.111.1B)…

[你必须知道的.NET]第三十回:.NET十年(下)

引言 语言是程序开发者行走江湖的手上利器&#xff0c;各大门派的高手在论坛、博客为了自家门派争吵不已早是技术世界中的亮丽风景&#xff0c;虽多少为刚刚踏入江湖的新手提供了思考的素材&#xff0c;但也同时迷惑了初出茅庐的前行方向。 本文不欲计较门派的高下&#xff0…

navcat定时备份mysql_Linux实现MYSQl数据库的定时备份

今天给大家分享一下如何在Linux下实现MYSQl数据库的定时备份。前提需要保证你的Linux服务器已经安装了MYSQl数据库服务。1、创建shell脚本vim backupdb.sh创建脚本内容如下&#xff1a;#!/bin/shdb_user"root"db_passwd"123456"db_name"userdb"n…

[你必须知道的.NET]第三十一回,深入.NET 4.0之,从“新”展望

总体来说&#xff0c;这是一篇介绍性的文章&#xff0c;不会涉及过多技术细节和研究过程。但是&#xff0c;作为拉开序幕的第一页&#xff0c;本文以提纲挈领的方式展开对.NET 4.0的初次体验。从What’s new的角度&#xff0c;开始我对.NET 4.0新特性的探索之旅。既然是介绍&am…

iphone电压测试软件,‎App Store 上的“ECG Test Pro”

超过1000份真实患者的异常静态心电图案例&#xff0c;供医学院学生或老师作为心电学习的辅助数据。> 医学生或实习生&#xff0c;可通过这个应用学习各种各样的心电病例> 医学院老师&#xff0c;可把这个应用作为教学素材&#xff0c;进行案例教学APP STORE 上最具有影响…

idea远程调试修改代码_IDEA远程调试(Remote Debug)Java代码指南

前言当我们的代码在线上/测试环境运行出现异常需要进行问题定位时,之前的传统做法是:查看异常日志,根据日志定位到出错代码,然后再根据相关参数及异常信息进行推断。但是很多异常问题需要更细致的进行debug才能够更精准的去定位和解决&#xff0c;这种情况下&#xff0c;我们希…

苹果计算机磁盘格式,Mac怎么将ntfs格式的磁盘格式化

1. 首先下载NTFS For Mac。下载之后就可以读取NTFS磁盘。2. 插入要格式化的NTFS磁盘。您可以在Mac OS X下通过命令行格式化NTFS磁盘。按照以下步骤进行操作&#xff1a;启动命令行&#xff1a;应用程序 》 工具 》 终端; 输入diskutil获取帮助。格式化命令图&#xff1a;使用di…

[你必须知道的.NET]第三十二回,,深入.NET 4.0之,Tuple一二

Tuple&#xff0c;是函数式编程的概念之一&#xff0c;早见于Elang、F#等动态语言。不过&#xff0c;我第一次听说Tuple还早在2005年园子的Ninputer大牛提出在.NET 2.0实现Tuple的基本想法&#xff0c;我们可以通过以下地址仰慕当时的历史片段&#xff1a; 探讨.NET 2.0中Tuple…

支持商用吗_可商用的插画素材 | 美翻了

好素材在手&#xff0c;天下我有啊...哈哈哈喽大家周末好&#xff0c;那上周公子做的那份工作型插画模板呢&#xff0c;很多小伙伴都来问我素材是哪里找的&#xff0c;自己画的吗当然不是了&#xff01;其实我在文章中已经提到了&#xff0c;那有的人可能之前用过或可以自己找到…

永恒边境白羊座服务器维护,永恒边境升级攻略 速升50级技巧

永恒边境怎么升级快&#xff1f;分享永恒边境升级攻略&#xff0c;下面我们就一起来看看永恒边境速刷主线支线任务技巧&#xff0c;希望对大家有所帮助。20-30级篇在这个阶段&#xff0c;我们就主线任务和支线任务大家都不要错过了&#xff0c;都要好好抓住&#xff0c;我还可以…

[你必须知道的.NET]第三十三回,深入.NET 4.0之,LazyT点滴

对象的创建方式&#xff0c;始终代表了软件工业的生产力方向&#xff0c;代表了先进软件技术发展的方向&#xff0c;也代表了广大程序开发者的集体智慧。以new的方式创建&#xff0c;通过工厂方法&#xff0c;利用IoC容器&#xff0c;都以不同的方式实现了活生生实例成员的创生…

频数直方图的步骤_绘制频数直方图步骤

怎样用excel制作频率分布直方图给出简单的步骤~有截图的话更好。我不知道按哪个东西~而且还要弄什么频(转载于word帮助文件&#xff0c;建议大家使用word时遇到问题按F1搜索帮助)使用直方图显示数据全部显示利用分析工具库的直方图工具&#xff0c;您可以分析数据并将其显示在直…