C#中的继承 - 覆盖和虚拟

时间:2018-02-15 20:39:06

标签: c# override virtual

我是C#覆盖和虚拟新手。在下面的例子中,我想从A类中的Caller方法调用B类中的Callee方法。 B继承A.有什么想法吗?

namespace Blah
{
    public class Program
    {
        public static void Main(string[] args)
        {
            A a = new A();
            a.Caller();
        }
    }

    class A
    {
        public void Caller()
        {
            Console.WriteLine("In Caller");
            Callee(); // How to make this call B:Callee() and make it print "in B"
        }

        public virtual void Callee()
        {
            Console.Write("In A");
        }
    }

    class B : A
    {
        public override void Callee()
        {
            Console.Write("In B");
        }
    }
}

2 个答案:

答案 0 :(得分:3)

如果要在类Callee内调用B方法,首先要创建此类的实例,然后调用此方法:

var b = new B();
B.Callee();

如果您正在寻找(尽管从实际角度来看没有意义),您应该将以上两行放在课程Caller中的方法A内。

通常我们定义一个基类,如果我们认为我们定义的类中的方法可以从我们的类派生的类中重新实现,我们将该方法标记为虚拟。当我们从基类派生一个类并且我们不覆盖虚方法时,则调用已在基类中定义的方法。而当我们覆盖基类中定义的虚方法时,会调用派生类中的方法。

答案 1 :(得分:1)

在您的示例中,您具有基类A,其子类B会覆盖A中的方法。这意味着您创建了一个替代A,可以作为A进行互动,但可能会有不同的行为。

但是,这并不意味着A的每个实例都突然开始使用此定义。在您的示例中,您创建了A的硬实例,但由于重写方法位于B,因此永远不会调用它。

相反,您应该创建B的实例,您可以将其转换为A。允许您的代码将其视为A对象,即使其为B

在您的示例中,您唯一需要做的就是创建Bfiddle)的实例:

    A a = new B();
    a.Caller(); 
    // Prints:
    //   In Caller
    //   In B

这种方式的工作方式与Java继承大致相同,只有在C#中才需要将方法标记为virtual才能覆盖它们。

但是,如果您的目的是更改CalleeA的定义而无需创建B(因此new A().Caller()将打印出“In B”),你应该重新思考你想要做的事情。它与虚拟方法完全不同,在大多数情况下,您应该尽量避免使用。