当在列表上下文中使用时,kotlin class 扩展解析父 class 的值而不是子值

kotlin class extensions resolve parent class's value instead of childs when used in list context

我正在使用 Kotlin (1.3.20) 中的 class 扩展,在扩展父 class 和子 运行 时我遇到了问题 class 在同一个 属性 上,然后使用那些列表的实例。

基本上发生的事情是子 class 的实例 return 是为父 class 的 属性 设置的值,而我没有明白为什么会这样。 我希望下面代码中的第 16 行 return "ext-special-thing" 但它确实 return "ext-thing" 即使 b[1] 中的实例肯定是 ExtSpecialThing 类型。

我怀疑原因是 extension-properties/extension-functions 在引擎盖下的工作方式(顺便说一句:这个问题也存在于扩展函数中);但我不是这方面的专家。

tl;dr: 第 16 行失败...为什么?

import kotlin.test.*

fun main (args : Array<String>) {
    assertEquals("ext-special-thing", ExtSpecialThing().prop)

    var a = listOf(ImplThing(), ImplSpecialThing())
    assertTrue(a[0] is ImplThing)
    assertTrue(a[1] is ImplSpecialThing)
    assertEquals("impl-thing",         a[0].prop)
    assertEquals("impl-special-thing", a[1].prop)

    var b = listOf(ExtThing(), ExtSpecialThing())
    assertTrue(b[0] is ExtThing)
    assertTrue(b[1] is ExtSpecialThing)
    assertEquals("ext-thing",         b[0].prop)
    assertEquals("ext-special-thing", b[1].prop) // fails ... why?
}

// ======================================
open class ImplThing () {
    open val prop : String = "impl-thing"
}
class ImplSpecialThing : ImplThing() {
    override val prop : String = "impl-special-thing"
}

// -------------------------------------
open class ExtThing () {}
class ExtSpecialThing : ExtThing () {}

val ExtThing.prop : String get() = "ext-thing"
val ExtSpecialThing.prop : String get() = "ext-special-thing"

这是官方描述的docs

We would like to emphasize that extension functions are dispatched statically, i.e. they are not virtual by receiver type. This means that the extension function being called is determined by the type of the expression on which the function is invoked, not by the type of the result of evaluating that expression at runtime.

这意味着以下内容将使您的测试成功:

assertEquals("ext-special-thing", (b[1] as ExtSpecialThing).prop)