dynamic - Kotlin 中动态/双重调度的限制是什么?

标签 dynamic dispatch kotlin

我刚刚开始探索 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/

相关文章:

go - 在 Go 中使用接口(interface)调度方法

c# - 调用接口(interface)成员的虚方法的CLR实现

Android Studio Kotlin 自动完成符号

java - 无法在Kotlin中解析字符串到文件

kotlin - 伴生对象中的对象实例

java - 使用Reflections动态加载包中的所有类

excel - 从动态日期范围中排除周末

javascript - 动态Web表单,字段可以嵌套到任意深度,还可以动态添加/删除字段

swift - 在 Swift 中将动态 Int 变量从一个类传递到另一个类

swift - 间接调用在 Swift 3 中调用了错误的专用泛型函数