Kotlin中Dynamic Dispatch机制疑问:为何输出3而非预期的4
Kotlin动态分发与方法调用解析
先看你的代码执行流程:
open class Shape { open fun number(m: Shape) = "1" open fun number(m: Rectangle) = "2" } class Rectangle : Shape() { override fun number(m: Shape) = "3" override fun number(m: Rectangle) = "4" } fun main() { val shape: Shape = Rectangle() println(shape.number(shape)) // 输出3而非预期的4 }
核心原因:方法调用分两步——静态选签名,动态找实现
Kotlin(和Java一致)的方法调用分为两个关键阶段:
- 静态绑定(编译期):编译器根据变量的静态类型(即声明时的类型,而非实际指向的对象类型)选择匹配的方法重载签名。
- 这里变量
shape的静态类型是Shape,传入参数shape时,编译器只会匹配接受Shape类型参数的number方法,也就是number(Shape)这个签名,完全不会考虑参数的实际类型是Rectangle。
- 这里变量
- 动态分发(运行期):确定签名后,JVM会根据调用者的实际对象类型(此处为Rectangle),找到该类型中对应签名的重写实现。
- 因为Rectangle重写了
number(Shape)方法返回"3",所以最终调用的是这个方法,输出3。
- 因为Rectangle重写了
为什么不会匹配number(Rectangle)?
重载方法的选择是编译期行为,只看静态类型。哪怕参数实际是Rectangle,但编译器看到的参数类型是Shape,就只会绑定number(Shape)的签名。如果想要调用number(Rectangle),需要让参数的静态类型为Rectangle,比如:
val rect: Rectangle = Rectangle() println(rect.number(rect)) // 输出4
或者在运行期做类型转换:
val shape: Shape = Rectangle() println(shape.number(shape as Rectangle)) // 输出4
内容的提问来源于stack exchange,提问作者Andrea
相关产品推荐
相关产品推荐

