You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

泛型方法参数对象的多态行为疑问:为何调用FirstChild的Fun方法

问题解答:为何调用FirstChild的Fun方法而非SecondChild的?

先梳理下你的代码里的关键细节:

  • SecondChild类中用*new关键字定义了Fun(),而非override*
  • 泛型方法Test<T>的约束为where T : Parent,方法内调用entity.Fun()

核心原因:方法隐藏(new) 与 方法重写(override) 的本质差异

首先要明确这两个关键字的核心区别:

  • 使用override时,你是真正覆盖了基类的虚方法,运行时会根据对象的实际类型触发对应的方法(这就是多态的核心)
  • 使用new时,你只是在SecondChild的类作用域内创建了一个同名的新方法,它并没有加入基类的虚方法调用链。也就是说,这个隐藏的方法只有在**编译时类型为SecondChild**的情况下才会被调用;一旦对象被当作基类(Parent或FirstChild)引用,就会走原本的虚方法链。

举个直观的对比例子:

SecondChild child = new SecondChild();
child.Fun(); // 输出"In SecondChild"——编译时类型是SecondChild,调用隐藏的方法
Parent p = child;
p.Fun(); // 输出"In FirstChild"——编译时类型是Parent,走虚方法链

你的Test方法调用逻辑和上面的p.Fun()完全一致。

泛型方法的调用逻辑解析

泛型方法Test<T>的约束T : Parent意味着,编译器在编译这个方法时,只会将entity视为Parent类型(因为T的上限是Parent)。虽然你传入的是SecondChild对象,但在方法内部,entity.Fun()调用的是Parent中定义的虚方法,而这个虚方法的重写链在FirstChild的override版本就终止了——因为SecondChild的Fun()是用new隐藏的,根本没有加入到这个虚方法链中。

后台是否存在强制转换?

并没有显式的强制转换操作,但编译器在处理泛型方法时,会将entity按照Parent类型来处理(受限于约束的上限)。运行时,CLR会遵循虚方法的调用规则,根据对象的实际类型找到最匹配的重写方法——也就是FirstChild的Fun(),而SecondChild的隐藏方法不在这个调用链里,因此不会被触发。

如果希望Test方法调用SecondChild的Fun(),只需要把SecondChild中的new替换为override,这样它就会加入到虚方法链中,运行时就会调用它的版本了。


内容的提问来源于stack exchange,提问作者Henry159

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:59:07