我刚刚开始探索Kotlin,并且对它超出Java核心动态绑定(bind)/调度语义的范围感到好奇。
假设我写的代码看起来像这样:
动物类{
有趣的add(x:Animal)= Animal()
}
对象马:动物
对象驴:动物
M子:动物
有趣的Horse.add(x:Horse)= Horse()
有趣的Horse.add(x:Donkey)= Mule()
fun main(args:Array){
val h:动物=马
val d:动物=驴
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中的默认方法有很大的不同,它们是根据运行时类型动态调度的,并且可以被覆盖。