我刚刚开始探索 Kotlin,我很好奇它超越 Java 的核心动态绑定(bind)/调度语义有多远。
假设我编写的代码看起来像这样:
class Animal {
fun add(x:Animal) = Animal()
}
object Horse : Animal
object Donkey : Animal
object Mule : Animal
fun Horse.add(x: Horse) = Horse()
fun Horse.add(x: Donkey) = Mule()
fun main(args : Array<String>) {
val h: Animal = Horse
val d: Animal = Donkey
val child = h + d
}
基于上面的代码,我期望会发生什么?我是否会在运行时失败,因为 Horse
没有实现 add(Animal)
?它能否在上述性质的调用中准确区分它们,其中被比较的值的编译时类型是 Animal
(至少,如所写)但它们的运行时类型更具体?如果我们使用 var
而不是 val
会改变什么吗?
提前致谢。
编辑:修改了核心代码——我看到了第一响应者强调的问题,我没有想清楚。显然我还没有真正编译过这个,我仍然在概念层面上进行探索。
另外,我会在实际的编译器中试一试,但我担心在某些情况下它可以工作,而在其他情况下它不会基于一些我不完全理解的标准。我无法找到关于如何在 Kotlin 中实现动态调度的引用文档(就此而言,对于 Java 也不确定;几个月前我写了一些我认为可以基于 JVM 文档工作的东西,但它没有',而且我从来没有机会探究到底是为什么)。
无论如何,再次感谢!
最佳答案
所以这里有一个实际编译的代码版本:
fun main(vararg args: String) {
val h:Animal = Horse
val d:Animal = Donkey
val child = h + d
println(child)
}
open class Animal {
fun plus(x:Animal) = Animal()
}
object Horse : Animal()
object Donkey : Animal()
object Mule : Animal()
fun Horse.plus(x:Horse) = Horse
fun Horse.plus(x:Donkey) = Mule
结果是“Animal@1906bcf8”。
据我所知,扩展方法,即 Horse.plus(x:Horse)
和 Horse.plus(x:Donkey)
是静态调度的。这是因为它们基本上被编译为与以下 Java 代码相同的字节码:
static Horse plus(Horse $receiver, Horse x) {
return Horse.INSTANCE;
}
顺便说一下,这与 Java 8 中的默认方法有很大的不同,后者是根据运行时类型动态调度的,并且可以被覆盖。
关于dynamic - Kotlin 中动态/双重调度的限制是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30408010/