关于C#中new关键字阻断重写及多态调用结果的技术咨询
C#中new关键字阻断重写及多态调用结果的技术咨询
这是个非常经典的C#多态与new关键字的混淆问题,咱们一步步拆解清楚,先把代码贴出来方便对照:
public class A { public virtual void Write() { Console.Write("A"); } } public class B : A { public override void Write() { Console.Write("B"); } } public class C : B { new public virtual void Write() { Console.Write("C"); } } public class D : C { public override void Write() { Console.Write("D"); } } // ... D d = new D(); C c = d; B b = c; A a = b; d.Write(); c.Write(); b.Write(); a.Write();
为什么输出是DDBB而不是DDDD?
核心点要区分**override重写和new隐藏**的本质区别:
override是延续基类的虚拟方法链条,相当于在同一个“方法家族”里替换实现;new是完全创建一个全新的虚拟方法,和基类的方法是两个独立的“家族”,只是名字相同而已。
咱们逐个梳理方法关系:
- A的
Write()是第一个虚拟方法,开启了一个方法链条; - B用
override重写了A的Write(),相当于把这个链条的实现替换成了自己的,此时A/B类型的引用调用Write()都会走这个链条; - C用
new public virtual void Write(),这里的new直接切断了和B的Write()的关联——C的Write()是个全新的虚拟方法,和A/B的Write()没有任何重写关系。此时C的对象里其实同时存在两个Write():一个是继承自B的(属于A的链条),一个是自己的新方法; - D用
override重写的是C的新虚拟方法,完全没碰A/B那个链条的方法。
再看每个调用的执行逻辑:
d.Write():D类型引用直接调用自己重写的C的方法,输出D;c.Write():C类型引用指向D对象,C的Write()是虚拟方法,D重写了它,所以调用D的实现,输出D;b.Write():B类型引用指向D对象,此时调用的是A→B链条的Write(),而D根本没重写这个链条的方法,所以执行B的实现,输出B;a.Write():A类型引用指向D对象,同样走A→B的链条,执行B的实现,输出B。
为什么实际对象是D,但b.Write()没有调用D的Write()?
因为D的Write()重写的是C的新方法,和B的Write()属于两个完全独立的方法体系。C用new关键字把自己的Write()和B的Write()彻底拆分开了,D并没有参与A→B那个方法链条的重写,所以当你用B类型的引用调用Write()时,只会识别到A→B链条的方法,和D重写的那个方法毫无关系。
备注:内容来源于stack exchange,提问作者Mike Lol
相关产品推荐
相关产品推荐

