我有三个简单的课程:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
我正在创建对象并调用他们的方法:
A a = new A();
a.Write();
A b = new C();
b.Write();
C c = new C();
c.Write();
Run Code Online (Sandbox Code Playgroud)
输出将是: ABC
我无法理解的是这些代码产生的原因B?:
A b = new C();
b.Write();
Run Code Online (Sandbox Code Playgroud)
我认为它应该是C.但是,我测试了很多次,而且它总是如此B.
我理解A b = new C()创建C的新对象类型.所以输出应该是C.或者在我们使用它而不进行转换时调用重写方法是特殊行为?
为什么会这样?因为我们没有使用任何B类的引用.
如果你使用它会工作 ((C)b).Write();
使用new关键字,您不会覆盖WriteC 的方法,而是创建仅为C定义的新方法.因此,对于C,您实际上有2个方法名称的方法Write.
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();
Run Code Online (Sandbox Code Playgroud)
当您将c定义为时,会发生同样的情况C:
C c = new C();
c.Write(); //Output "C"
((A)c).Write(); //Output "B"
Run Code Online (Sandbox Code Playgroud)
在第一个示例中,您将调用在C上定义的新方法.在第二行中,您Write从A 调用方法,该方法被B覆盖,因此输出"B".
编辑:(更多解释)
变量c属于类型A,因此您的编译器知道"c是A的实例",不知道它实际上是更多派生类型.当你Write在它上面调用方法时,它将调用在A上定义的方法(由B覆盖).你的基类A不知道你在C上定义的新方法(这就是new创建一个新方法),所以除非你把它转换为C让编译器知道c你的基本方法的实际派生类型课程将被调用.