C#从重写方法调用基类方法:两种实例化方式的差异
两种m_canvas调用方式的差异说明
先明确给定的类定义:
public abstract class T_BaseClass { public virtual void m_canvas() { Console.WriteLine("canvas method called from template."); } } public class C_ChildT : T_BaseClass { public override void m_canvas() { base.m_canvas(); Console.WriteLine("canvas method called from child template."); } }
两种调用方式的代码
方式一
C_ChildT mychildclass = new C_ChildT(); mychildclass.m_canvas();
方式二
T_BaseClass mychildclass1 = new C_ChildT(); mychildclass1.m_canvas();
核心差异分析
执行结果完全一致
两种方式调用后,控制台输出完全相同:
canvas method called from template. canvas method called from child template.
这是因为C_ChildT重写了父类的virtual方法,无论变量声明类型是父类还是子类,CLR都会根据实例的实际类型(C_ChildT)执行重写后的方法。
变量类型与绑定机制的差异
- 方式一中,变量
mychildclass的声明类型和实际实例类型都是C_ChildT:编译器在编译阶段就能明确要调用的是C_ChildT的m_canvas,不过因为方法是虚方法,最终还是会通过运行时多态绑定确认(这里编译和运行时目标方法一致)。 - 方式二中,变量
mychildclass1的声明类型是父类T_BaseClass,实际实例类型是子类C_ChildT:编译阶段编译器只能识别父类的virtual方法,但运行时CLR会根据实例的真实类型找到子类重写的方法执行,这就是C#的运行时多态特性。
扩展性差异
如果后续给C_ChildT新增父类没有的方法(比如public void NewMethod()),方式一的变量可以直接调用mychildclass.NewMethod();而方式二的变量必须先强制转换为C_ChildT类型(((C_ChildT)mychildclass1).NewMethod())才能调用,因为编译器只认可变量声明类型(父类)的成员。
内容的提问来源于stack exchange,提问作者JudgeDreed
相关产品推荐
相关产品推荐

