2013-07-16 73 views
6

我想了解倍率在C#中的需要,虛擬的,所以我寫了下面的代碼:如果派生類不重寫該方法,應該調用哪個版本?

using System; 
namespace Override 
{ 
    class Base 
    { 
     public virtual void method() 
     { 
      Console.WriteLine("Base method"); 
     } 
    } 
    class Derived : Base 
    { 
     public override void method() 
     { 
      Console.WriteLine("Derived method"); 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Derived d = new Derived(); 
      d.method(); 
     } 
    } 
} 

我期待「派生法」被稱爲和printed.Then我寫了下面的代碼,而不使用虛擬/超控組合。

using System; 
namespace Override 
{ 
    class Base 
    { 
     public void method() 
     { 
      Console.WriteLine("Base method"); 
     } 
    } 
    class Derived : Base 
    { 
     public void method() 
     { 
      Console.WriteLine("Derived method"); 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Derived d = new Derived(); 
      d.method(); 
     } 
    } 
} 

而且我得到了相同的結果,即「派生法」打來電話,printed.My問題是,如果代碼工作沒有虛擬/覆蓋如我所料,什麼是他們的需求?或者我在這裏錯過了什麼?

+0

難道你在第二個關於隱藏方法的警告? 「'Derived.Method()'隱藏繼承的成員Base.Method()'。如果隱藏是有意的,請使用new關鍵字\t」 – Sayse

+0

謝謝大家的回答,現在我明確了這個概念 – ZoomIn

回答

11

在您的源代碼中,您總是在沒有任何多態行爲的情況下進行簡單的繼承。您始終創建派生類的實例並將其分配給派生類實例變量。

DerivedClass d = new DerivedClass(); // here no polymorphism, and only inheritance is there 

所以,當你將使用類變量調用方法時,總是會調用DerivedClass方法,無論該方法是虛擬的或沒有父類。

在多態性中,您的程序不知道您正在調用方法的類的確切類型(這個概念稱爲遲綁定)。如下例所示:

BaseClass b = new DerivedClass(); // here b is a base class instance but initiated using derived class 

致電b。()方法,它會做後期綁定,將顯示多態行爲(僅當該方法已被設置在基類虛擬)

注:虛擬關鍵字延遲綁定到正確的方法的版本運行時,是核心keywork實現多態。因此,對於確切的多態行爲,在父類中聲明方法爲虛函數,然後在子類中聲明該方法。

+0

Thanks - the keyword for我在這裏是「延遲綁定」。 – Eccountable

8

virtual允許根據編譯時不可用的信息在運行時選擇正確版本的方法。考慮下面的調整,以你的例子:

using System; 
namespace Override 
{ 
    class Base 
    { 
     public virtual void method() 
     { 
      Console.WriteLine("Base method"); 
     } 
    } 
    class Derived : Base 
    { 
     public override void method() 
     { 
      Console.WriteLine("Derived method"); 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Derived d = new Derived(); 
      Base b = d; 
      b.method(); 
     } 
    } 
} 

隨着virtual/override,該代碼會顯示Derived method,在運行時,我們可以看到,b確實是一個Derived實例。如果沒有virtual/override,它將顯示Base method,因爲b的聲明類型爲Base

0

Derived類的方法'method'將隱藏Base類的實現,這就是爲什麼你得到了消息「Derived method」的原因。

虛擬和抽象有很多用途,但是一個例子是你在基類中有功能的地方,它可能不適合從你的基類繼承的所有類的情況。使用虛擬允許另一個類完全覆蓋該功能並提供自己的實現。

3

這裏是你錯過了測試:

Base d = new Derived(); 
d.method(); // "Derived method" 

Base b = new Base(); 
b.method(); // "Base method" 

而且設想一下,如果你有這樣的分別由不同的繼承對象Base對象的集合。關鍵字virtual允許那些對象瞭解它們在運行時的真實類型。

List<Base> collection = new List<Base>(); 
collection.Add(new Base()); 
collection.Add(new Derived()}; 
collection.Add(new Base()); 

foreach(Base b in collection) 
{ 
    b.method(); // will print out "Base" or "Derived" correctly 
} 
2

看到差異

 class Base 
     { 
      public void method() 
      { 
       Console.WriteLine("Base method"); 
      } 
     } 
     class Derived : Base 
     { 
      public void method() 
      { 
       Console.WriteLine("Derived method"); 
      } 
     } 
     class Program 
     { 
      static void Main(string[] args) 
      { 
       Derived d; 

       d = new Derived(); 
       d.method(); 

       d = new Base(); 
       d.method(); 
      } 
     } 

OUTPUT
派生方法
派生方法

  class Base 
      { 
       public virtual void method() 
       { 
        Console.WriteLine("Base method"); 
       } 
      } 
      class Derived : Base 
      { 
       public override void method() 
       { 
        Console.WriteLine("Derived method"); 
       } 
      } 
      class Program 
      { 
       static void Main(string[] args) 
       { 
        Derived d; 

        d = new Derived(); 
        d.method(); 

        d = new Base(); 
        d.method(); 
       } 
      } 

OUTPUT
派生方法
基地方法

+1

這將不會編譯,不能將d設置爲新的Base()。您的示例正在嘗試做與Chowletts相同的答案 – Sayse

2

基類指針可以用來指向基類或從鹼衍生的任何對象的反對。因此,當基類對象指向派生類時,虛擬方法的需求會變成圖片

Base d = new Derived(); 
d.method(); // "Derived method" 
相關問題