C#-重写和虚拟继承

C#-重写和虚拟继承,c#,overriding,virtual,C#,Overriding,Virtual,我不熟悉C#覆盖和虚拟。在下面的示例中,我想从类中的调用方方法调用B类中的被调用方方法。B继承A.有什么想法吗 namespace Blah { public class Program { public static void Main(string[] args) { A a = new A(); a.Caller(); } } class A {

我不熟悉C#覆盖和虚拟。在下面的示例中,我想从类中的调用方方法调用B类中的被调用方方法。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");
        }
    }
}

如果要在类
B
中调用
被调用方
方法,必须首先创建此类的实例,然后调用此方法:

var b = new B();
B.Callee();
如果这是您正在寻找的(尽管从实际角度看这没有意义),您应该将上面两行放在类
a
中的方法
调用方


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

在您的示例中,基类
a
具有子类
B
,该子类重写
a
中的方法。这意味着您可以创建一个可选的
A
,它可以作为
A
进行交互,但可能具有不同的行为

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

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

在您的示例中,您只需要创建
B
()的实例:

其工作方式与Java继承大致相同,只是在C语言中,您需要将方法标记为
virtual
,以便覆盖它们


但是,如果您打算更改
A
Callee
的定义,而不必创建
B
(因此
新的A().Caller()
将在“B”中打印出来),那么您应该重新考虑您要做的任何事情。它与虚拟方法完全不同,在大多数情况下,您应该尽量避免使用它

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