虚拟function
我真的不明白 – 我什么时候应该使用虚拟function?如果有人能向我解释,我会很高兴,谢谢。
虚方法是多态的关键。 标记为虚拟的方法可以在派生类中重写,以更改或专门化类的行为。
例:
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 }
通过一个例子可能最容易理解所以想象我们有如下代码
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,并且方法不是虚拟的,所以声明的变量类型确定调用的方法,而如果方法是虚拟的,则对象的运行时类型是将被调用的方法的决定因素
虚函数是子类可以覆盖的函数
//在父母身上
public virtual string someMethod() { return "someting"; }
//在孩子身上
public override string someMethod() { return "someting else"; }
如果您希望更改(覆盖)子类中函数的行为,则使用虚函数。
class Order { public virtual long GetOrderNumber { return nextOrderNumber; } } class ExpressOrder : Order { public override long GetOrderNumber { return nextOrderNumber + 1000000; } }
如果已设置inheritance链,并且希望覆盖派生类中基类中定义的函数的默认实现,则只需要虚函数。
经典的例子如下:
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?"); } }
Dog
和Human
类都inheritance自Animal
类,因为它们都是动物类型。 但它们都以非常不同的方式说话,因此他们需要覆盖Speak
函数以提供自己独特的实现。
在某些情况下,在设计自己的类时使用相同的模式可能是有益的,因为这会启用多态 ,这实际上是不同的类共享一个公共接口并且可以通过代码进行类似处理的情况。
但我会回应其他人在评论中提出的建议:正确学习面向对象编程并不是你可以通过询问一些Stack Overflow问题来做的事情。 这是一个复杂的话题,值得投入时间作为开发人员学习。 我强烈建议你拿一本关于面向对象编程的书(特别是一本为C#语言编写的)并通过这些例子。 如果使用得当,OOP是一个非常强大的工具,但在设计不佳时肯定会成为障碍!
给定基类:
class SomeBaseClass() { public virtual string GetName() { return "SomeBaseClass"; } }
覆盖它时,inheritance该函数
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”
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(); } }
好的,现在你有两个class级。 关键是在不知道实际类是什么的情况下引用虚函数,例如:
public void PerformFiring(Weapon W) { // do stuff W.FireOnTarget(); // do more stuff }
此方法将使用您从Weapon派生的任何对象,并在该对象上调用FireOnTarget。 例如:
Pistol p=new Pistol(); PerformFiring(p);