虚拟功能

时间:2011-06-29 12:09:16

标签: c#

我真的不明白 - 我什么时候应该使用虚拟功能?如果有人能向我解释,我会很高兴,谢谢。

7 个答案:

答案 0 :(得分: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
}

答案 1 :(得分:1)

虚函数是子类可以覆盖的函数

//在父母

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

//在孩子身上

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

答案 2 :(得分:1)

通过一个例子可能最容易理解所以想象我们有如下代码

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和d是完全相同的对象!

上述结果将是:

基础虚拟

派生覆盖

派生覆盖

基础非虚拟

在派生

中定义的新方法

基础非虚拟

尽管最后两行在同一对象上调用方法名称NotVirtual。因为te变量声明为Base和Derived,并且方法不是虚拟的,所以声明的变量类型确定调用的方法,而如果方法是虚拟的,则对象的运行时类型是将被调用的方法的决定因素

答案 3 :(得分:0)

如果您希望更改(覆盖)子类中函数的行为,则使用虚函数。

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

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

答案 4 :(得分: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,这实际上是不同的类共享一个公共接口,并且可以通过代码进行类似处理。 / p>

但我会回应其他人在评论中提出的建议:正确学习面向对象的编程并不是你可以通过询问一些Stack Overflow问题来做的事情。这是一个复杂的话题,值得投入时间作为开发人员学习。我强烈建议你选择一本关于面向对象编程的书(特别是一本为C#语言编写的),并通过这些例子。如果使用得当,OOP是一个非常强大的工具,但如果设计得很差,肯定会成为一个障碍!

答案 5 :(得分: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”

答案 6 :(得分:-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
}

此方法将使用您从Weapon派生的任何对象,并在该对象上调用FireOnTarget。例如:

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