【问题标题】:What are the limits on dynamic/double dispatch in Kotlin?Kotlin 中动态/双重调度的限制是什么?
【发布时间】:2015-08-05 03:27:39
【问题描述】:

我刚刚开始探索 Kotlin,我很好奇它在 Java 的核心动态绑定/调度语义之外还有多远。

假设我编写的代码如下所示:

类动物{ 有趣的添加(x:动物)=动物() } 对象马:动物 对象驴:动物 对象骡子:动物 有趣的 Horse.add(x:Horse) = Horse() fun Horse.add(x:Donkey) = Mule() 有趣的主要(参数:数组){ val h:动物 = 马 val d:动物 = 驴 val 孩子 = h + d }

根据上面的代码——我可以期待会发生什么?由于 Horse 没有实现 add(Animal),我在运行时会失败吗?它能否在上述性质的调用中准确区分它们,其中被比较的值的编译时类型是 Animal(至少,如所写),但它们的运行时类型更具体?如果我们使用 var 而不是 val,它会改变什么吗?

提前致谢。

编辑:修改的核心代码——我看到第一响应者突出显示的问题,我没有想清楚。显然我还没有真正编译过这个,我还在概念层面上进行探索。

另外,我将在实际编译器中试一试,但我担心它会在某些情况下工作,而在其他情况下,它不会基于我不完全理解的某些标准。我无法找到有关如何在 Kotlin 中实现动态调度的参考文档(就此而言,我也不确定 Java 的情况;几个月前我写了一些我认为可以基于 JVM 文档工作的东西,但它没有't,而且我从来没有机会去探究究竟是为什么)。

无论如何再次感谢!

【问题讨论】:

    标签: dynamic dispatch kotlin


    【解决方案1】:

    所以这是你的代码的一个实际编译的版本:

    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 中的默认方法有很大的不同,默认方法是基于运行时类型动态分派的,并且可以被覆盖。

    【讨论】:

    • 非常感谢!很有意义。我将通过我自己的探索更进一步。
    【解决方案2】:

    此代码根本不可编译,因为 Animal 没有任何“+”运算符。

    如果他们允许对动物使用马“+”方法, 那么你会得到运行时错误,其中 kotlin/java/etc.试图阻止。

    Kotlin 不会使用运行时类型来解析方法和东西, 因为有可能产生运行时错误。

    如果另一个线程同时将 Animal 更改为 Mule 怎么办,另一个线程更改 Animal 的确切行/时间是不确定的,因此这可能会导致运行时错误。

    Val 或 var 在这种情况下不会改变任何东西。

    【讨论】:

    • 感谢您的反馈;我看到了问题。我修改了问题代码,希望更接近合理。
    猜你喜欢
    • 2019-10-21
    • 2018-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-16
    • 1970-01-01
    • 2018-07-25
    相关资源
    最近更新 更多