C#向上转型后调用基类virtual方法为何执行派生类override实现
问题原因解释
你原有的认知「向上转型后无法访问子类独有方法」是完全正确的,你观察到的虚方法调用子类实现的现象是C#多态机制的正常表现,核心和两个概念、虚方法的调用规则相关:
1. 编译时类型与运行时类型的区别
- 编译时类型:即你声明变量时显式指定的类型,你代码中
Shape shape = circle;的编译时类型为Shape,C#编译器在编译阶段只会校验你调用的方法是否存在于编译时类型的定义中,所以你只能调用Shape类公开的Draw()和duplicate(),无法直接调用Circle独有的FillCircle(),这就是你原有认知的底层逻辑。 - 运行时类型:即变量实际指向的堆中实例的真实类型,你这里给
shape赋值的是new Circle()创建的实例,所以运行阶段这个变量指向的实例类型始终是Circle,不会因为你用父类类型引用它就发生改变。
2. 虚方法的调用规则
C#中被virtual关键字标记的方法属于虚方法,子类可以通过override关键字重写该方法的实现。虚方法的调用逻辑为:
运行时会优先调用实例运行时类型中重写后的实现,只有当运行时类型没有重写该虚方法时,才会退而调用编译时类型的基类实现。
你代码中的Draw()符合这个规则:基类Shape标记为virtual,子类Circle用override重写了实现,运行时检测到实例真实类型为Circle,所以最终执行的是Circle的Draw()逻辑。
而duplicate()没有被标记为virtual,也没有被子类重写,属于非虚方法,非虚方法的调用只会绑定编译时类型的实现,所以不管你用Shape还是Circle类型的变量调用,都会执行基类的duplicate()逻辑。
补充说明
如果需要调用子类的独有方法,你可以对shape变量做向下转型:
// 向下转型回Circle类型 Circle circle = shape as Circle; if (circle != null) { circle.FillCircle(); // 可以正常调用子类独有方法 }
内容的提问来源于stack exchange,提问作者baudi27
相关产品推荐
相关产品推荐

