2011-06-29 173 views
4

我真的不明白 - 我什麼時候應該使用虛擬功能?如果有人能夠向我解釋,我會很高興,謝謝。虛擬功能

+9

我推薦閱讀一本關於C#和OOP的初級讀物。 – CodesInChaos

+0

可能的重複[在c#中實際使用虛函數](http://stackoverflow.com/questions/1062102/practical-usage-of-virtual-functions-in-c) – onof

+0

我建議避免_public virtuals_,use _template method_ pattern以這種方式:[看這裏我的上一篇文章](http://stackoverflow.com/questions/6478175/remove-object-from-generic-list-by-id/6520579#6520579) – sll

回答

13

虛擬方法是關鍵polymorphism一個子類可以重寫。標記爲虛擬的方法可以在派生類中被重寫,以改變或專門化類的行爲。

例子:

class Base 
{ 
    public virtual void SayHello() 
    { 
     Console.WriteLine("Hello from Base"); 
    } 
} 

class Derived : Base 
{ 
    public override void SayHello() 
    { 
     Console.WriteLine("Hello from Derived"); 
    } 
} 

static void Main() 
{ 
    Base x = new Base(); 
    x.SayHello(); // Prints "Hello from Base" 
    x = new Derived(); 
    x.SayHello(); // Prints "Hello from Derived" 
} 

注意,您可以重新聲明(未覆蓋)不是虛的方法,但在這種情況下,它不會參與多態性

class Base 
{ 
    public void SayHello() // Not virtual 
    { 
     Console.WriteLine("Hello from Base"); 
    } 
} 

class Derived : Base 
{ 
    public new void SayHello() // Hides method from base class 
    { 
     Console.WriteLine("Hello from Derived"); 
    } 
} 

static void Main() 
{ 
    Base x = new Base(); 
    x.SayHello(); // Prints "Hello from Base" 
    x = new Derived(); 
    x.SayHello(); // Still prints "Hello from Base" because x is declared as Base 
    Derived y = new Derived(); 
    y.SayHello(); // Prints "Hello from Derived" because y is declared as Derived 
} 
+0

這是更好的解釋,非常感謝! –

1

虛函數是那些如果它希望

//父

public virtual string someMethod() 
    { 
     return "someting"; 
    } 

//兒童

public override string someMethod() 
    { 
     return "someting else"; 
    } 
+0

右邊的詞是「覆蓋」 – onof

+0

我知道,但是什麼時候需要使用覆蓋?也許一個例子可以幫助。 –

+0

在父項中虛擬,覆蓋子項。 – Jason

0

虛函數如果您希望更改(覆蓋)子類中函數的行爲,則可以使用它。

class Order 
{ 
    public virtual long GetOrderNumber { return nextOrderNumber; } 
} 

class ExpressOrder : Order 
{ 
    public override long GetOrderNumber { return nextOrderNumber + 1000000; } 
} 
0

你只需要虛函數,如果你設置了一個繼承鏈,並要覆蓋在派生類的基類中定義的函數的默認實現。

典型的例子是東西如下:

public class Animal 
{ 
    public virtual void Speak() 
    { 
     Console.WriteLine("..."); 
    } 
} 

public class Dog : Animal 
{ 
    public override void Speak() 
    { 
     Console.WriteLine("Bow-wow"); 
    } 
} 

public class Human : Animal 
{ 
    public override void Speak() 
    { 
     Console.WriteLine("Hello, how are you?"); 
    } 
} 

無論是DogHuman類從基Animal類繼承,因爲它們是兩種類型的動物。但是他們都以不同的方式說話,所以他們需要重寫Speak函數來提供他們自己獨特的實現。

在某些情況下,在設計自己的類時使用相同的模式會是有益的,因爲這會啓用polymorphism,這基本上是不同類共享通用接口的地方,並且可以由您的代碼進行類似處理。

但是我會迴應其他人在評論中提出的建議:正確學習面向對象的編程不是通過詢問幾個Stack Overflow問題就能做到的。這是一個複雜的話題,作爲一名開發人員的學習,您值得投入時間。我強烈建議拿起一本關於面向對象編程的書(特別是爲C#語言編寫的書)並閱讀示例。使用正確的OOP是一個非常強大的工具,但如果設計得不好,肯定會成爲障礙!

+0

很高興知道人類是動物:D –

+0

感謝您的解釋:) –

0

如果有一個基類:

class SomeBaseClass() 
{ 
    public virtual string GetName() 
    { 
     return "SomeBaseClass"; 
    } 
} 

當你重寫它,你繼承了功能

class SomeDerivedClass() : SomeBaseClass 
{ 
} 

所以,當你說:

SomeDerivedClass sdc = new SomeDerivedClass(); 
Console.WriteLine(sdc.GetName()); //outputs "SomeBaseClass" 

GetName()返回 「SomeBaseClass」

然而你可以,override吧。

class SomeDerivedClass() 
{ 
    public override string GetName() 
    { 
     return "SomeDerivedClass"; 
    } 
} 

這裏GetName()現在將返回「SomeDerivedClass」

1

可能比較容易通過一個例子來理解這樣IMAGIN我們有像下面

class Base{ 
public virtual string VirtualMethod(){ 
    return "base virtual"; 
} 

public string NotVirtual(){ 
    return "base non virtual"; 
} 
} 

class Derived : Base{ 
    public override string VirtualMethod(){ 
     return "Derived overriden"; 
    } 
    public new string NotVirtual(){ 
     return "new method defined in derived"; 
    } 
} 

} 

代碼,如果你使用的代碼如下

Base b = new Base(); 
    Derived d = new Derived(); 
    Base b2 = d; 

    Console.WriteLine(b.VirtualMethod()); 
    Console.WriteLine(d.VirtualMethod()); 
    Console.WriteLine(b2.VirtualMethod()); 

    Console.WriteLine(b.NotVirtual()); 
    Console.WriteLine(d.NotVirtual()); 
    Console.WriteLine(b2.NotVirtual()); 

值得關注的是,b2廣告是完全相同的對象!

的上述結果將是:

基本虛擬

派生重寫

派生重寫

鹼非虛擬

在衍生定義

新方法

基礎非虛擬

儘管最後兩行在同一個對象上調用了方法名NotVirtual。由於te變量聲明爲Base和Derived,且該方法不是虛擬的,變量的聲明類型決定了調用的方法,而如果方法是虛擬的,則該對象的運行時類型是決定使用哪種方法的因素,即

-1
public abstract class Weapon 
{ 
    public virtual abstract FireOnTarget(); 
} 

public class Pistol : Weapon 
{ 
    public override FireOnTarget() 
    { 
     LoadPowder(); 
     LoadBullet(); 
     CockIt(); 
     PullTheTrigger(); 
    } 
} 

public class SucideBomber : Weapon 
{ 
    public override FireOnTarget() 
    { 
     BuyTruck(); 
     LoadWithC4(); 
     DriveToTarget(); 
     ActivateDetonator(); 
    } 
} 

好吧,現在你有兩個類。問題的關鍵是指虛擬函數不知道實際的類是有什麼,比如:

public void PerformFiring(Weapon W) 
{ 
    // do stuff 
    W.FireOnTarget(); 
    // do more stuff 
} 

此方法將使用任何對象,你發送的,從得到的武器,並呼籲FireOnTarget該對象上。例如:

Pistol p=new Pistol(); 
PerformFiring(p);