新关键字:为什么不调用派生方法?

时间:2016-02-25 12:20:04

标签: c# inheritance

我有三个简单的课程:

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

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

class C : B
{
    public new void Write()
    {
        Console.Write("C");
    }
}

我正在创建对象并调用他们的方法:

A a = new A();
a.Write();

A b = new C();
b.Write();

C c = new C();
c.Write();

输出将是:ABC

我无法理解为什么这些代码产生B

A b = new C();
b.Write();

我认为它应该是C。但是,我测试了很多次,它总是B

我理解A b = new C()创建了C的新对象类型。因此输出应该是C.或者在我们使用它而不进行转换时调用重写方法是特殊行为?

为什么会这样?因为我们没有使用任何对B类的引用。

2 个答案:

答案 0 :(得分:6)

如果你使用((C)b).Write();

,它会奏效

使用new关键字,您不会覆盖C的Write方法,而是创建仅为C定义的新方法。因此对于您的C,您实际上有2个方法名称为{的方法{ {1}}。

Write

将c定义为A c = new C(); c.Write(); //Output "B", you're calling the overridden method ((C)c).Write(); //Output "C", you're calling the method defined on C //or (c as C).Write(); 时会发生同样的情况:

C

在第一个示例中,您将调用在C上定义的新方法。在第二行中,您从A调用C c = new C(); c.Write(); //Output "C" ((A)c).Write(); //Output "B" 方法,该方法被B覆盖,因此输出Write

编辑:(更多解释)

变量"B"属于A类型,因此您的编译器知道“c是A的实例,不知道它实际上是更多派生类型。当您在其上调用方法c时,它将调用在A上定义的方法(由B覆盖)。你的基类A不知道你在C上定义的新方法(这是Write所做的,创建一个新方法),所以除非你把它转换为C让编译器知道{的实际派生类型{1}},将调用基类的方法。

答案 1 :(得分:0)

我现在真的很晚了,没有回答这个问题,但我需要这种行为,以防万一其他人需要它,我会分享它。 要获得这种行为,您需要使用接口,例如

interface Writer{
 void write;
}

class A : Writer
{
    void Writer.Write()
    {
        Console.Write("A");
    }
}

其他人也一样。如您所见,您必须显式实现它,也必须显式调用它。

A c = new C();
((Writer) c).write()

;