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

标签 inheritance kotlin class-extensions

我正在使用Kotlin(1.3.20)中的类扩展,并且在同一属性上扩展父类和子类,然后使用列表的实例时遇到了问题。

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

我怀疑原因是扩展属性/扩展功能在幕后的工作方式(顺便说一句:扩展功能也存在此问题);但是我在这方面不是专家。

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) 

关于inheritance - 在列表上下文中使用kotlin类扩展时,解析父类的值而不是子类的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56390542/

相关文章:

spring - 如何在 Spring Boot 应用程序中注入(inject) Prometheus 指标 bean?

objective-c - 将代码从 Xcode 3 移动到 4 会产生错误 : Cannot declare variable inside @interface or @protocol

objective-c - 静态变量和类扩展中的变量有什么区别?

ios - "Expected expression in Swift key path"使用扩展重构代码时出错

c++ - 派生类是单例是一个好习惯吗

android - 带 map 的 Kotlin (标记未显示)

python - 仅获取类的已声明方法(不包括继承类的方法)

android - 单击EditText后隐藏键盘

Python super() 参数 : why not super(obj)?

java - 子接口(interface)如何重用其父接口(interface)的实现?