2015-07-02 35 views
3

這是一個在C#中重寫的問題。在C#中重寫,使兩個後續的方法虛擬

當我使用下面的代碼:

class Program 
{ 


    class A 
    { 
     public virtual void callme() 
     { 
      Console.WriteLine("this is A"); 
     } 
    } 
    class B : A 
    { 
     public new virtual void callme() 
     { 
      Console.WriteLine("this is B"); 
     } 
    } 
    class C : B 
    { 
     public override void callme() 
     { 
      Console.WriteLine("this is C"); 
     } 
    } 


    static void Main(string[] args) 
    { 
     A obj = new C(); 
     obj.callme(); 
     Console.ReadKey(); 
    } 
} 

OUTPUT:This is A

當我使用:

class Program 
{ 


    class A 
    { 
     public virtual void callme() 
     { 
      Console.WriteLine("This is A."); 
     } 
    } 
    class B : A 
    { 
     public override void callme() 
     { 
      Console.WriteLine("This is B."); 
     } 
    } 
    class C : B 
    { 
     public override void callme() 
     { 
      Console.WriteLine("This is C."); 
     } 
    } 


    static void Main(string[] args) 
    { 
     A obj = new C(); 
     obj.callme(); 
     Console.ReadKey(); 
    } 
} 

OUTPUT:This is C.

所以,如果我做的方法在隨後的類(A以及B),爲什麼它調用的最後一個方法,如果B類重寫AC是壓倒B然後它調用C的方法是虛擬的。

請解釋。

+5

這正是您不應忽視編譯器警告的原因。 – leppie

回答

2

在第一種情況下,B是陰影A而C重寫了B中的陰影。所以只要引用類型是A,它就會調用A方法。

在第二種情況下B是重寫A和C重疊B(所以它是重寫A)。

參見:Differences Between Shadowing and Overriding

-1

...所以,如果我做的方法在隨後的類虛擬(A爲 以及B)爲什麼它調用的最後一個方法,而如果B類是 覆蓋和C是覆蓋然後它的調用C

在第一個例子中,你只是替換B和C類中的方法。所以當你將實例上傳到類A時,它只是使用類A中的方法。

第二部分是overriding方法和使用多態性來更改B類和C類中的方法行爲。當您覆蓋method - this方法不會被替換,而是永久更改。每當你再次調用這個方法時 - 它會用override關鍵字調用該方法。

更多信息:https://msdn.microsoft.com/en-us/library/ebca9ah3.aspx

PS 總之 - 如果你有 要更換新方法:

class A { MyMethod() {} }  Class B : A { MyMethod() {} } 

要覆蓋所有後續調用(即使是在父類)將採用重寫邏輯:

class A { virtual MyMethod() {} }  Class B : A { override MyMethod() {} } 
+0

如果你想用新的方法替換方法,你可以使用'new'關鍵字。 – fsacer

+0

不一定。如果您不使用「新」關鍵字,這不是一個錯誤 - 只是來自intellisense的警告。你會得到這個警告,因爲它不清楚你試圖通過在派生類中創建具有相同名稱的方法來實現。可能是無意的。因此,如果您的意圖是更換方法或使用虛擬 - 如果您的意圖是更改方法行爲,則要求您使用「新」關鍵字。 – Fabjan

+0

是的,它是必要的,因爲你實際上得到了編譯錯誤和警告。 – fsacer

1

檢查編譯器警告:

警告1'..Program.B.callme()'隱藏繼承成員 '..Program.A.callme()'。要使當前成員重寫 實現,請添加override關鍵字。否則,請添加新的 關鍵字。 ..\程序。cs 44 33測試

它聲明B中的方法隱藏了A中的方法。它只是覆蓋B中的方法而不是A(編譯器假定你在B類中是callme是一種新方法)。因此,當您撥打A.callme時,由於A中的方法未被覆蓋,它將返回「This is A」。

+0

可能是最清楚的解釋。幹得好:) – fsacer

+0

...「當你用C覆蓋方法;它只是覆蓋B中的方法而不是A(編譯器假定你在B類中的callme是一種新方法)」...這是不正確的。只有虛擬方法可以被重寫,所以在這個例子中,來自A類的方法被重寫(不是B)。 C類從類B繼承了此方法,它從父類A繼承了此方法... – Fabjan

+1

@Fabjan方法在B中也是虛擬的,檢查問題中的第一個示例,並且它隱藏了A中的實現。正確;不管你是否使用new關鍵字,B中的方法都是NEW方法,並且與A中的方法沒有關係。 – daryal