这里用示例C# Virtual Method进行了清楚的说明
您为什么将方法声明为“虚拟”。
使用虚拟有什么好处?
虚拟允许继承的类替换基类随后使用的方法。
public class Thingy
{
public virtual void StepA()
{
Console.Out.WriteLine("Zing");
}
public void Action()
{
StepA();
Console.Out.WriteLine("A Thingy in Action.");
}
}
public class Widget : Thingy
{
public override void StepA()
{
Console.Out.WriteLine("Wiggy");
}
}
class Program
{
static void Main(string[] args)
{
Thingy thingy = new Thingy();
Widget widget = new Widget();
thingy.Action();
widget.Action();
Console.Out.WriteLine("Press any key to quit.");
Console.ReadKey();
}
}
运行程序时,输出将是:
Zing
A Thingy in Action.
Wiggy
A Thingy in Action.
[请注意,即使Widget调用了在Thingy级别定义的Action()方法,在内部Thingy中还是调用了Widget的StepA()方法。
基本答案是它为类的继承者提供了更大的灵活性。当然,您必须精心设计课程,否则可能会造成严重破坏。
虚拟方法是一种方法,其中实际方法调用取决于基础对象的运行时类型。
非虚拟方法是一种方法,其中调用的实际方法取决于在方法调用时对象的引用类型。
虚拟关键字用于修改 方法或属性声明 在哪种情况下,方法或属性 被称为虚拟成员。的 虚拟成员的实现可以 由以下成员的主要成员更改 派生类。
当调用虚拟方法时, 检查对象的运行时类型 对于最重要的成员。的 最派生成员中的压倒性成员 类被调用,可能是 原始成员(如果没有派生类) 已覆盖该成员。 (更多 有关运行时类型和大多数信息 派生的实现,请参见10.5.3 虚方法。)
默认情况下,方法是非虚拟的。 您不能覆盖非虚拟的 方法。
您不能使用虚拟修饰符 使用以下修饰符:
静态 抽象 覆盖
虚拟属性的行为类似于 抽象方法,除了 声明和 调用语法。
- 在静态属性上使用虚拟修饰符是错误的。
- 虚拟继承的属性可以通过以下方式在派生类中重写: 包括一个财产声明 使用替代修饰符。
即使您不打算从该类派生,也可能需要将方法标记为虚方法以模拟该类。一些模拟框架仅允许您模拟虚拟方法。请注意,实现接口的方法是隐式虚拟的。
我使用RhinoMocks,它具有此限制,并且正因为这个原因,默认情况下已将我的方法标记为虚拟。对我来说,这可能是使用虚拟方法的最大原因,因为继承起作用的情况要少得多。
虚拟方法类似于基类中的抽象方法,不同之处在于它们在派生类上的实现是可选的。您也可以将逻辑放在虚拟方法中,并在派生类中重写它们。
为了能够在继承的类中重写它。
检查关键字的MSDN entry。这就更深入地解释了。
一个简短的问题,简短的答案!如果您认为自己将继承该方法所属的类,则将其限定为“虚拟”方法。
更长的答案:“虚拟使您可以重写,从而在派生类中赋予方法另一种含义。
不用说,当您的代码试图遵守Open Closed Principle时,虚拟方法会派上用场>
阅读鲍勃叔叔的原始OCP白皮书中的更多内容,关于开放式封闭原则here。>>
还请注意,默认情况下,与Java不同,C#中的方法默认为not
虚拟的。这里用示例C# Virtual Method进行了清楚的说明
虚拟函数是实际上不存在的函数。派生类可以通过覆盖它来修改虚拟函数。虚拟函数是实现运行时多态的方法之一
public class sample {
public virtual void fun(){
Console.WriteLine("base sample class \n");
}
}
public class A : sample{
public override void fun(){
Console.WriteLine("Class A \n");
}
}
public class B : sample{
public override void fun(){
Console.WriteLine("Class B \n");
}
}
class run{
public static void main(String[] args){
sample obj = new sample();
sample obj1 = new A();
sample obj2 = new B();
obj.fun();
obj1.fun();
obj2.fun();
}
}
运行时发生在编译时。在将方法声明为虚拟方法时,在派生类中对其进行声明要求您添加override
或new
修饰符。我们可以看到当TrySpeak
。传递孩子和父亲时,都调用Speak of Father,而TryScream
将调用每个方法。为了理解这一点,我们应该了解一些事情,在Child的实例中,Child类或父亲类有两个Scream
方法。我们可以从儿童班或父亲班叫Scream
。由于Virtaul
修饰符标记了该方法,因此可以被派生类覆盖,这意味着即使从父类调用Scream
,它也会被覆盖,如果使用新的修饰符,则该方法会有所不同。
import system;
class Father
{
Speak()
{
Console.Writeline("Father is speaking")
}
virtual Scream()
{
Console.Writeline("Father is screaming")
}
}
class Child: father
{
Speak()
{
Console.Writeline("Child is speaking")
}
override Scream()
{
Console.Writeline("Child is screaming")
}
}
class APP
{
public static void Main()
{
// We new two instances here
Father father = new Father();
Child child = new Child();
// Here we call their scream or speak through TryScream or TrySpeak
TrySpeak(father);
TrySpeak(child);
//>>>"Father is speaking"
//>>>"Father is speaking"
TryScream(father);
TryScream(child);
//>>>"Father is screaming"
//>>>"Child is screaming"
}
// when your method take an Parameter who type is Father
// You can either pass in a Father instance or
// A instance of a derived Class from Father
// which could be Child
public static void TrySpeak(Father person)
{
person.Scream();
}
public static void TryScream(Father person)
{
person.Speak();
}
}
虚拟方法与非虚拟方法之间的区别。
我们有两堂课;一个是Vehicle
using System; namespace VirtualExample { class Vehicle { public double distance=0.0; public double hour =0.0; public double fuel =0.0; public Vehicle(double distance, double hour, double fuel) { this.distance = distance; this.hour = hour; this.fuel = fuel; } public void Average() { double average = 0.0; average = distance / fuel; Console.WriteLine("Vehicle Average is {0:0.00}", average); } public virtual void Speed() { double speed = 0.0; speed = distance / hour; Console.WriteLine("Vehicle Speed is {0:0.00}", speed); } } class Car : Vehicle { public Car(double distance, double hour, double fuel) : base(distance, hour, fuel) { } public void Average() { double average = 0.0; average = distance / fuel; Console.WriteLine("Car Average is {0:0.00}", average); } public override void Speed() { double speed = 0.0; speed = distance / hour; Console.WriteLine("Car Speed is {0:0.00}", speed); } } class Program { static void Main(string[] args) { double distance,hour,fuel=0.0; Console.WriteLine("Enter the Distance"); distance = Double.Parse(Console.ReadLine()); Console.WriteLine("Enter the Hours"); hour = Double.Parse(Console.ReadLine()); Console.WriteLine("Enter the Fuel"); fuel = Double.Parse(Console.ReadLine()); Car objCar = new Car(distance,hour,fuel); Vehicle objVeh = objCar; objCar.Average(); objVeh.Average(); objCar.Speed(); objVeh.Speed(); Console.Read(); } } }
希望帮助!
在C#中,要覆盖派生类中的基类方法,您必须将基类方法声明为虚拟,派生类方法声明为重写,如下所示:
using System;
namespace Polymorphism
{
class A
{
public virtual void Test() { Console.WriteLine("A::Test()"); }
}
class B : A
{
public override void Test() { Console.WriteLine("B::Test()"); }
}
class C : B
{
public override void Test() { Console.WriteLine("C::Test()"); }
}
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
C c = new C();
a.Test(); // output --> "A::Test()"
b.Test(); // output --> "B::Test()"
c.Test(); // output --> "C::Test()"
a = new B();
a.Test(); // output --> "B::Test()"
b = new C();
b.Test(); // output --> "C::Test()"
Console.ReadKey();
}
}
}
您还可以通过使用virtual和new关键字来混合方法隐藏和方法重写,因为派生类的方法可以同时是virtual和new。当您要覆盖派生类方法到下一个级别时,这是必需的,因为我正在覆盖C类中的B类,Test()方法,如下所示:
using System;
namespace Polymorphism
{
class A
{
public void Test() { Console.WriteLine("A::Test()"); }
}
class B : A
{
public new virtual void Test() { Console.WriteLine("B::Test()"); }
}
class C : B
{
public override void Test() { Console.WriteLine("C::Test()"); }
}
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
C c = new C();
a.Test(); // output --> "A::Test()"
b.Test(); // output --> "B::Test()"
c.Test(); // output --> "C::Test()"
a = new B();
a.Test(); // output --> "A::Test()"
b = new C();
b.Test(); // output --> "C::Test()"
Console.ReadKey();
}
}
}
金字:virtual关键字用于修改在基类中声明的方法,属性,索引器或事件,并允许在派生类中重写它。
override关键字用于将虚拟/抽象方法,属性,索引器或基类的事件扩展或修改为派生类。
new关键字用于将基类的方法,属性,索引器或事件隐藏到派生类中。
ENJOY:-)
此链接将通过一个非常简单的示例为您提供更好的理解https://stackoverflow.com/a/2392656/3373865
这里用示例C# Virtual Method进行了清楚的说明
虚拟函数是实际上不存在的函数。派生类可以通过覆盖它来修改虚拟函数。虚拟函数是实现运行时多态的方法之一
运行时发生在编译时。在将方法声明为虚拟方法时,在派生类中对其进行声明要求您添加override
或new
修饰符。我们可以看到当TrySpeak
。传递孩子和父亲时,都调用Speak of Father,而TryScream
将调用每个方法。为了理解这一点,我们应该了解一些事情,在Child的实例中,Child类或父亲类有两个Scream
方法。我们可以从儿童班或父亲班叫Scream
。由于Virtaul
修饰符标记了该方法,因此可以被派生类覆盖,这意味着即使从父类调用Scream
,它也会被覆盖,如果使用新的修饰符,则该方法会有所不同。
虚拟方法与非虚拟方法之间的区别。
在C#中,要覆盖派生类中的基类方法,您必须将基类方法声明为虚拟,派生类方法声明为重写,如下所示:
此链接将通过一个非常简单的示例为您提供更好的理解https://stackoverflow.com/a/2392656/3373865