2010-06-01 47 views
25

我有以下類:困惑在C# 「覆蓋」 與 「新」

class Base 
{ 
    public virtual void Print() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

class Der1 : Base 
{ 
    public new virtual void Print() 
    { 
     Console.WriteLine("Der1"); 
    } 
} 

class Der2 : Der1 
{ 
    public override void Print() 
    { 
     Console.WriteLine("Der2"); 
    } 
} 

這是我的主要方法:

Base b = new Der2(); 
Der1 d1 = new Der2(); 
Der2 d2 = new Der2(); 

b.Print(); 
d1.Print(); 
d2.Print(); 

輸出爲BaseDer2Der2

據我所知,Override不會讓以前的方法運行,即使指針指向它們。所以第一行也應輸出Der2。但是Base出來了。

這怎麼可能?覆蓋如何在那裏不起作用?

+0

真是一個驚人的例子... 唯一的技巧就是在這裏 - intially,BASE的方法是通過的「DER-1」的虛方法隱藏的,所以在騎的「方法DER-2 「無法實施。因此,我們獲得了BASE的價值。 – Kings 2015-05-07 15:21:05

回答

27

你從來沒有真正覆蓋Base版本的Print()。您只在Der1中用一個單獨的虛擬方法(命名相同)隱藏它。

當您在方法簽名上使用new關鍵字時 - 您告訴編譯器,這是一種恰好與您的某個基類的方法名稱相同的方法 - 但沒有其他關係。你可以使這個新方法變成虛擬的(就像你所做的那樣),但這不像重寫基類方法一樣。

Der2當你重寫Print你實際上是覆蓋您在Der1聲明的「新」版本 - 不是版本爲Base。 Eric Lippert有一個excellent answer這個稍微不同的問題,可以幫助你推斷如何在C#語言中處理虛擬方法。

在您的例子,當你調用Print,你在呼喚它在第一種情況下,通過Base類型的引用 - 這樣的隱藏(但沒有覆蓋)的Print版本被調用。另外兩個調用被調度到Der1的實現,因爲在這種情況下,你實際上已經覆蓋了該方法。

您可以在MSDN documentation of new and override中閱讀更多關於此的內容。

你可能已經打算與Der1做(因爲你DER2做的)是使用override關鍵字:

class Base 
{ 
    public virtual void Print() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

class Der1 : Base 
{ 
    // omitting 'new' and using override here will override Base 
    public override void Print() 
    { 
     Console.WriteLine("Der1"); 
    } 
} 
+0

這就是他對Der2所做的。 – GalacticCowboy 2010-06-01 20:09:26

+0

@GalacticCowboy - 的確,那是我的觀點。這可能也是Der1中的目標,但不知何故,'new'關鍵字被滑入,而不是'override'。我會更新我的帖子,使其更清晰。 – LBushkin 2010-06-01 20:11:52

+0

謝謝。一個很好的答案,我完全理解它現在如何工作。 – iTayb 2010-06-01 20:18:13

5

這是因爲Der1覆蓋Print其與替換它全新的方法碰巧具有相同的名稱(這是由使用new關鍵字引起的)。所以,當物體投射到Base時,它會調用Print,Base;沒有覆蓋調用..

1

override將取代以往的方法,但你Der1類沒有重載Print()(它的陰影它,使用VB-ISM),然後BasePrint()的最優化版本被覆蓋的調用,這恰好是它定義的版本

0

正如大家所說的,Der1類正在取代Print()而不是覆蓋它。要看到這個動作,你可以基於d1d2Base,然後調用打印方法。然後它將返回Base

((Base)d2).Print(); //Base