Interface到底繼承於Object嗎?之我見
今天和同事討論了一個問題:Interface到底繼承於Object嗎?
我看過的所有關於.Net的書都告訴我“所有的型別都是繼承於System.Object的”,那麼理所當然
Interface也是繼承於System.Object的,以下面程式碼為例:
class Program
{
static void Main(string[] args)
{
IATM account = new ATMMachine();
account.GetMoney(600);
Console.WriteLine(account.ToString());
Console.ReadKey();
}
}
public interface IATM
{
void GetMoney(Decimal amount);
}
public class ATMMachine : IATM
{
private Decimal b;
public void GetMoney(Decimal amount)
{
b += amount;
}
public override string ToString()
{
return String.Format("Getted Money = {0,6:C}", b);
}
}
{
static void Main(string[] args)
{
IATM account = new ATMMachine();
account.GetMoney(600);
Console.WriteLine(account.ToString());
Console.ReadKey();
}
}
public interface IATM
{
void GetMoney(Decimal amount);
}
public class ATMMachine : IATM
{
private Decimal b;
public void GetMoney(Decimal amount)
{
b += amount;
}
public override string ToString()
{
return String.Format("Getted Money = {0,6:C}", b);
}
}
將程式碼編譯以後用IL DASM反編譯後檢視IATMde IL程式碼,如下:
.class interface public abstract auto ansi ConsoleApplication2.IATM
{
} // end of class ConsoleApplication2.IATM
和其他型別做比較如:
.class private auto ansi beforefieldinit ConsoleApplication2.Program
extends [mscorlib]System.Object
{
} // end of class ConsoleApplication2.Program
都有.Class這個標識,說明事實上Interface也是一個Class,只是它是一個特殊的Class,同時說明一個問題,
IATM介面並沒有繼承System.Object,否則就應該有extends [mscorlib]System.Object這句話。那麼到底Interface
繼承了什麼呢?利用AL DASM 檢視後設資料檔案(Ctrl+M)後有如下片段:其中02000003標識Interface:IATM,02000004標識Class:ATMMachine
TypeDef #2 (02000003)
-------------------------------------------------------
TypDefName: ConsoleApplication2.IATM (02000003)
Flags : [Public] [AutoLayout] [Interface] [Abstract] [AnsiClass] (000000a1)
Extends : 01000000 [TypeRef]
Method #1 (06000003)
-------------------------------------------------------
MethodName: GetMoney (06000003)
Flags : [Public] [Virtual] [HideBySig] [NewSlot] [Abstract] (000005c6)
RVA : 0x00000000
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
1 Arguments
Argument #1: ValueClass System.Decimal
1 Parameters
(1) ParamToken : (08000002) Name : amount flags: [none] (00000000)
TypeDef #3 (02000004)
-------------------------------------------------------
TypDefName: ConsoleApplication2.ATMMachine (02000004)
Flags : [Public] [AutoLayout] [Class] [AnsiClass] [BeforeFieldInit] (00100001)
Extends : 01000001 [TypeRef] System.Object
Field #1 (04000001)
-------------------------------------------------------
Field Name: b (04000001)
Flags : [Private] (00000001)
CallCnvntn: [FIELD]
Field type: ValueClass System.Decimal
Method #1 (06000004)
-------------------------------------------------------
MethodName: GetMoney (06000004)
Flags : [Public] [Final] [Virtual] [HideBySig] [NewSlot] (000001e6)
RVA : 0x0000208f
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
1 Arguments
Argument #1: ValueClass System.Decimal
1 Parameters
(1) ParamToken : (08000003) Name : amount flags: [none] (00000000)
注意Extends標識,它表明當前型別繼承了什麼型別,從這裡也可以看出IATM沒有繼承System.Object,否則應該有Extends : 01000001 [TypeRef] System.Object這句描述,
01000000 [TypeRef] 是什麼呢?我理解是什麼都不繼承,開啟mscorlib.dll有如下後設資料描述片段:
TypeDef #1 (02000002)
-------------------------------------------------------
TypDefName: System.Object (02000002)
Flags : [Public] [AutoLayout] [Class] [Serializable] [AnsiClass] [BeforeFieldInit] (00102001)
Extends : 01000000 [TypeRef]
Method #1 (06000001)
-------------------------------------------------------
MethodName: .ctor (06000001)
Flags : [Public] [HideBySig] [ReuseSlot] [SpecialName] [RTSpecialName] [.ctor] (00001886)
RVA : 0x000020d0
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments.
CustomAttribute #1 (0c000001)
-------------------------------------------------------
CustomAttribute Type: 06003055
CustomAttributeName: System.Runtime.ConstrainedExecution.ReliabilityContractAttribute :: instance void .ctor(value class System.Runtime.ConstrainedExecution.Consistency,value class System.Runtime.ConstrainedExecution.Cer)
Length: 12
Value : 01 00 03 00 00 00 01 00 00 00 00 00 > <
ctor args: ( )
這裡的Extends標識後的內容也是01000000 [TypeRef],所以我推測Interface和System.Object都沒有繼承於任何型別。
實際上,這裡的01000000(即0X01000000)是後設資料標識(Metadata Token),它是個4-byte的值,最高位用來標識當前的後設資料型別,例如:01代表該條後設資料是一個TypeRef,02代表TypeDef,04代表FieldDef,06代表MethodDef,08代表 ParamDef,對於最低3位,簡單的說可以看成當前後設資料在後設資料表中的索引(實際上後設資料表的儲存是很複雜的),例如0x0400001B代表這條後設資料是一個Field,它在後設資料表中的索引位置是第27行,那麼從0X01000000可以看出,它表示的是當前後設資料標識的型別是一個TypeRef並且它在後設資料表中的索引位置是0,其實在後設資料表的索引位置0處是不儲存任何資料的,所以這樣的標識被稱作“Nil”標識。
最後是一個疑問:
IATM account = new ATMMachine(); IATM account; (當然這樣寫會編譯不通過,但是智慧感知依然有效)
account.GetMoney(600); 或者 account.GetMoney(600);
在IDE中敲入account.後會發現除了IATM中定義的GetMoney方法外還有ToString、GetType、Equals、GetHashCode這四個方法,那麼現在明明是用IATM介面來訪問物件,而IATM並沒有Extends System.Object,所以這裡智慧感知應該只出現GetMoney這個方法才對,可是事實卻不是這樣,那麼這是為什麼呢?我也沒有從後設資料中找到答案,希望各位高手能指點一二。
另外我做如下猜測:通過介面所能訪問的應該只有Class或者Struct,而只要是託管程式碼中的型別,不管是Class還是Struct都是繼承於System.Object的(Struct繼承於System.ValueType,而System.ValueType繼承於System.Object),因此System.Object中定義的以上四個方法總是對外公開的,所以我感覺是不是在邏輯上可以看成是Interface和System.Object都Extends了一個擁有這四種方法的“介面”,所有的Interface都隱式提供了上述四種契約而在.NET編譯器編譯時令所有介面包含這四種契約。 最後,通過修改後設資料可以去掉Extends : 01000000 ....然後編譯成新的dll並且這個dll可用,我覺得這個時候的程式碼已經不是託管程式碼了,不符合CLS規範了,所以以此來推出並不是所有型別都繼承於System.Object可能不太合適。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-609228/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- python3父類需要繼承object嗎?Python繼承Object
- JavaSE-繼承(包含Object類)Java繼承Object
- 使用Object.create()實現繼承Object繼承
- C++繼承一之公有繼承C++繼承
- javascript之繼承JavaScript繼承
- js之繼承JS繼承
- JAVA 之 繼承Java繼承
- oop 之繼承OOP繼承
- 公有繼承、私有繼承和保護繼承之間的對比繼承
- odoo 繼承(owl繼承、web繼承、view繼承)Odoo繼承WebView
- Java類是如何預設繼承Object的?Java繼承Object
- JavaScript(2)之——繼承JavaScript繼承
- python之繼承Python繼承
- JavaScript之物件繼承JavaScript物件繼承
- python 基礎之繼承、重寫、多繼承Python繼承
- 類&成員可見性&繼承繼承
- JAVA物件導向高階:繼承:許可權修飾符(繼承注意事項) 單繼承 Object類 方法重寫Java物件繼承Object
- 組合優於繼承繼承
- <十>關於菱形繼承繼承
- JavaScript進階之繼承JavaScript繼承
- 面試必問之繼承面試繼承
- JS專題之繼承JS繼承
- JavaScript 學習之繼承JavaScript繼承
- 物件導向之繼承物件繼承
- 原型,繼承——原型繼承原型繼承
- 菱形繼承,虛繼承繼承
- JS繼承,中間到底幹了些什麼JS繼承
- 你真的理解JS的繼承了嗎?JS繼承
- JAVA中的註解可以繼承嗎?Java繼承
- 多繼承 與 多重繼承繼承
- [許可權設計]組的繼承:需要從多個父組繼承嗎?繼承
- C++繼承詳解:共有(public)繼承,私有(private)繼承,保護(protected)繼承C++繼承
- 講清楚之 javascript 物件繼承JavaScript物件繼承
- Java之繼承和抽象類Java繼承抽象
- 物件導向之_繼承概念物件繼承
- Java介面之間的繼承Java繼承
- Javascript之繼承(原型鏈方式)JavaScript繼承原型
- c#屬性之繼承C#繼承