C# 虚拟函数
我真的不明白-我什么时候应该使用虚拟函数?如果有人能给我解释一下,我会很高兴的,谢谢。虚拟函数是子类可以重写的函数,如果它愿意的话 //父母C# 虚拟函数,c#,C#,我真的不明白-我什么时候应该使用虚拟函数?如果有人能给我解释一下,我会很高兴的,谢谢。虚拟函数是子类可以重写的函数,如果它愿意的话 //父母 public virtual string someMethod() { return "someting"; } //在儿童时期 public override string someMethod() { return "someting else"; } 虚拟方法是成功
public virtual string someMethod()
{
return "someting";
}
//在儿童时期
public override string someMethod()
{
return "someting else";
}
虚拟方法是成功的关键。标记为virtual的方法可以在派生类中重写,以更改或专门化类的行为 例如:
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 Order
{
public virtual long GetOrderNumber { return nextOrderNumber; }
}
class ExpressOrder : Order
{
public override long GetOrderNumber { return nextOrderNumber + 1000000; }
}
如果您已经设置了继承链,并且希望覆盖派生类中基类中定义的函数的默认实现,则只需要虚拟函数 经典的例子如下:
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
类都继承自基本的Animal
类,因为它们都是动物类型。但是它们都以非常不同的方式说话,因此它们需要重写speak
函数以提供自己独特的实现
在某些情况下,在设计自己的类时使用相同的模式可能是有益的,因为这样可以启用,这本质上就是不同的类共享一个公共接口,并且可以由代码进行类似的处理
但我将回应其他人在评论中的建议:正确地学习面向对象编程不是通过问几个堆栈溢出问题就能做到的。这是一个复杂的话题,也是一个值得作为开发人员投入时间学习的话题。我强烈建议你读一本关于面向对象编程的书(特别是一本为C语言编写的书)并仔细阅读这些例子。如果正确使用OOP,它是一个非常强大的工具,但如果设计不当,它肯定会成为一个障碍 给定一个基类:
class SomeBaseClass()
{
public virtual string GetName()
{
return "SomeBaseClass";
}
}
当您重写它时,您将继承该函数
class SomeDerivedClass() : SomeBaseClass
{
}
所以当你说:
SomeDerivedClass sdc = new SomeDerivedClass();
Console.WriteLine(sdc.GetName()); //outputs "SomeBaseClass"
GetName()
返回“SomeBaseClass”
但是,您可以覆盖它
class SomeDerivedClass()
{
public override string GetName()
{
return "SomeDerivedClass";
}
}
这里的
GetName()
现在将返回“SomeDerivedClass”可能是通过一个示例最容易理解的,想象一下我们有如下代码
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 a d是完全相同的对象
上述结果将是:
基本虚拟
派生重写
派生重写
基本非虚拟
派生类中定义的新方法
基本非虚拟
即使最后两行调用同一对象上的方法名NotVirtual。由于te变量声明为基本变量并派生,且方法不是虚拟的,因此声明的变量类型决定调用的方法,而如果方法是虚拟的,则对象的运行时类型是将调用的方法的决定因素
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
}
Pistol p=new Pistol();
PerformFiring(p);
此方法将使用您发送的来自武器的任何对象,并对该对象调用FireOnTarget。例如:
public void PerformFiring(Weapon W)
{
// do stuff
W.FireOnTarget();
// do more stuff
}
Pistol p=new Pistol();
PerformFiring(p);
我知道,但我什么时候需要使用覆盖?也许举个例子会有所帮助。在父对象中是虚拟的,在子对象中是重写的。我建议读一本关于C#和OOP的入门书。可能重复的我建议避免公共虚拟,使用模板方法模式如下:试着看以下答案:谢谢解释:)