我有三个简单的课程:
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
类的引用。
答案 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()
;