using System; using System.Collections.Generic; using System.Linq; using System.Text; public class BaseClass { public virtual void displayName() { Console.WriteLine("BaseClass"); } } public class DerivedClass : BaseClass { public virtual void displayName() { Console.WriteLine("DerivedClass"); } } public class SubDerivedClass:DerivedClass { public override void displayName() { Console.WriteLine("SubDerivedClass"); } } public class SuperDerivedClass:SubDerivedClass { public void displayName() { Console.WriteLine("SuperDerivedClass"); } } class Program { static void Main(string[] args) { SuperDerivedClass superDerivedClass = new SuperDerivedClass(); SubDerivedClass subDerivedClass = superDerivedClass; DerivedClass derivedClass = superDerivedClass; BaseClass baseClass = superDerivedClass; superDerivedClass.displayName(); subDerivedClass.displayName(); derivedClass.displayName(); baseClass.displayName(); } }執行結果
superDerivedClass.displayName();
不需解釋。沒有子類,所以無多態。
subDerivedClass.displayName();
subDerivedClass重寫了DerivedClass的方法,則subDerivedClass中的displayName也是虛方法,於是運行時要從繼承鏈中盡量找派生得最遠的虛方法,發現其子類SuperDerivedClass沒有用override,這意味著SuperDerivedClass只是覆蓋了displayName方法,沒有重寫它。所以並不執行SuperDerivedClass的displayName,而執subDerivedClass的displayName。
derivedClass.displayName();
DerivedClass覆蓋了(是覆蓋,不是重寫,因為沒有override標簽)BaseClass的方法,但這個覆蓋的方法被聲明為virtual,於是運行時要從繼承鏈中盡量找派生得最遠的虛方法,發現其子類SubDerivedClass重寫了這個方法,於是從SubDerivedClass繼續往下找,找到SuperDerivedClass時,發現SuperDerivedClass覆蓋了這個方法,沒有重寫,所以最終執行SubDerivedClass的displayName方法。
baseClass.displayName();
在BaseClass中displayName是個虛方法,於是它要試圖找派生的最遠的虛方法。但找到DerivedClass就發現,DerivedClass已經把displayName覆蓋了,這條虛鏈於是就斷了。所以就直接執行BaseClass的方法了。
注意:
如果把SubDerivedClass的override去掉,則試圖在SuperDerivedClass中寫public override void displayName()是編譯不過的。因為雖然在DerivedClass中有虛的displayName可供子類override,但由於SubDerivedClass中的DerivedClass沒有加override,這相當於SubDerivedClass覆蓋了DerivedClass的displayName方法,而非override了它,於是在SuperDerivedClass看到的displayName,其實是SubDerivedClass的dislayName,是一個非虛的方法,而不是從DerivedClass傳承下來的虛方法,所以不能override
若一個類中有一個方法,則只在兩種情況下該方法才會是一個虛方法。
1:該方法用virtual定義。
2:該類的父類中有一個同名的虛方法,在該類中用override關鍵字重寫了父類的虛方法。
子類要想“重寫”而非“覆蓋”父類的方法,要滿足兩個條件。
一:“父類方法是虛方法。(這意味著該方法或者是有virtual標記的,或者是override它的父類的。)”。
二:“子類中有override標記”。
這二者缺一,則意味著子類是對父類的方法進行了“覆蓋”,而非“重寫”。
如果一個方法是虛方法(),則運行時從找那個“重寫”得最遠的方法來執行。一旦遇到“覆蓋”,則繼承鏈就斷掉了。