Kotlin的动态/双重调度有什么限制?

我刚开始研究Kotlin,我很好奇它超越了Java的核心动态绑定/调度语义。

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

    类动物{
         fun add(x:Animal)=动物()
     }

    对象马:动物
    对象驴:动物
    对象骡:动物

    有趣Horse.add(x:Horse)=马()
    有趣的Horse.add(x:驴子)=骡子()

     fun main(args:Array){
         val h:动物=马
         val d:动物=驴
         val孩子= h + d
     }

根据上面的代码 – 我可以期望发生什么? 因为Horse没有实现add(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中的默认方法来说是一个很大的区别,它们是基于运行时类型动态调度的,并且可以被重写。

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

如果他们允许在动物上使用Horse“+”方法,那么你会得到运行时错误,kotlin / java /等等。 试图阻止。

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

如果另一个线程在同一时间将动物改变为骡,那么另一个线程改变动物的确切线/时间是不确定的,所以这可能导致运行时错误。

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