2012-11-13 185 views
5

期待「來自派生的問候」。但得到「從基地你好。」。爲什麼調用基類方法代替派生類方法?

class Program 
{ 
    interface IBase 
    { 
     void Method(); 
    } 

    public class Base: IBase 
    { 
     public virtual void Method() 
     { 
      Console.WriteLine("Hello from the base."); 
     } 
    } 

    public class Derived : Base 
    { 
     public virtual new void Method() 
     { 
      Console.WriteLine("Hello from the derived."); 
     } 
    } 

    static void Main(string[] args) 
    { 
     IBase x = new Derived(); 
     x.Method(); 
    } 
} 

那麼,爲什麼不調用派生類的方法。更重要的是,我怎樣才能讓派生類的方法被調用,而不需要將x強制轉換爲派生類型?

在我的實際應用中,IBase有其他幾種相關的方法,派生只取代IBase中的兩種方法。

回答

6

當您使用new修改你特別說,該方法是不是虛擬分發鏈的該層次結構的一部分,所以調用由基類的同名方法不會導致重定向孩子班。如果您用override而不是new標記該方法,則會看到您期望看到的虛擬分發。

您還需要從派生類的方法中刪除virtual,因爲您不能將override方法標記爲virtual(它已經是)。

如果你真的不想重寫該方法,那麼在你的情況下,根本不使用繼承可能更合適。你可能只是想以獨佔使用接口:

public interface IFoo 
{ 
    void Foo(); 
} 

public class A : IFoo 
{ 
    public void Foo() 
    { 
     Console.WriteLine("I am A, hear me roar!"); 
    } 
} 

public class B : IFoo 
{ 
    public void Foo() 
    { 
     Console.WriteLine("I am B, hear me roar!"); 
    } 
} 

private static void Main(string[] args) 
{ 
    IFoo foo = new A(); 
    foo.Foo(); 

    foo = new B(); 
    foo.Foo(); 

    Console.WriteLine(); 
    Console.WriteLine("Press any key to exit . . ."); 
    Console.ReadKey(true); 
} 
+0

+10對於錯誤的解釋。 – 2012-11-13 15:35:39

+0

建議您建議解決方案不可構建。編譯器抱怨「無法覆蓋成員'Program.Base.Method()',因爲它沒有被標記爲虛擬的,抽象的或者被覆蓋的。 – estimpson

+0

基本方法必須標記爲'虛擬'並且派生方法'覆蓋' –

2

在子類中使用override關鍵字而不是virtual new

因此,你的代碼應該是這樣的:

class Program 
{ 
    interface IBase 
    { 
     void Method(); 
    } 

    public class Base: IBase 
    { 
     public virtual void Method() 
     { 
      Console.WriteLine("Hello from the base."); 
     } 
    } 

    public class Derived : Base 
    { 
     public override void Method() // The magic happens here! 
     { 
      Console.WriteLine("Hello from the derived."); 
     } 
    } 

    static void Main(string[] args) 
    { 
     IBase x = new Derived(); 
     x.Method(); 
    } 
} 

如上所述here,該new關鍵字用來隱藏父類的方法,這是不是你要找的東西。

+3

也就是說,不要使用'new'。 – cadrell0

+0

+10如果您將更正的代碼添加到您的答案。 – 2012-11-13 15:28:28

+0

@SteveHémond我認爲他不需要添加代碼來顯示一個單詞的變化,但是如果答案能夠正確地提及哪些單詞需要更正(新的和虛擬的)或解釋它的重要性,那就太好了。 – Servy

3

這是基本的polymorphism在工作。

對於你要找的,你需要設置你的派生的方法來覆蓋繼承方法的行爲:

public class Derived : Base 
{ 
    public override void Method() 
    { 
     Console.WriteLine("Hello from the derived."); 
    } 
} 
1

new關鍵字創建一個新的方法,並說基本方法是隱藏的。但是它只適用於派生類的消費者,因爲基類代碼對它沒有任何瞭解。

override關鍵字用新的關鍵字覆蓋基類實現。

class Program 
{ 
    interface IBase 
    { 
     void Method(); 
    } 

    public class Base: IBase 
    { 
     public virtual void Method() 
     { 
      Console.WriteLine("Hello from the base."); 
     } 
    } 

    public class Derived : Base 
    { 
     // the next line was changed. 
     public override void Method() 
     { 
      Console.WriteLine("Hello from the derived."); 

      // note that if you want to call the original implementation, you do it like this: 
      base.Method(); 
     } 
    } 

    static void Main(string[] args) 
    { 
     Base x = new Derived(); 
     x.Method(); 
    } 
} 
0

在派生只有在派生的情況下,它有效地隱藏了基實現存在new'd方法。

但IBase類型只知道Base的實現,所以它會調用它。

要回答你的問題,叫派生的實現你會怎麼做:

Derived d = new Derived(); 
d.Method(); 
((IBase)d).Method(); 

//Prints: 
//Hello from the derived. 
//Hello from the base. 
相關問題