gpt4 book ai didi

kotlin - 绑定(bind)类引用返回协变类型的目的是什么?

转载 作者:行者123 更新时间:2023-12-04 20:31:17 25 4
gpt4 key购买 nike

我正在玩反射,我遇到了这个问题。通过 ::class 使用绑定(bind)类引用时语法,我得到一个协变的 KClass 类型:

fun <T> foo(entry: T) {
with(entry::class) {
this // is instance of KClass<out T>
}
}

正如我从文档中了解到的,这将返回对象的确切类型,以防它是 T 的子类型的实例。 ,因此是方差修饰符。
但是,这会阻止检索在 T 中声明的属性。上课并获得他们的值(value)(这就是我想要做的)
fun <T> foo(entry: T) {
with(entry::class) {
for (prop in memberProperties) {
val v = prop.get(entry) //compile error: I can't consume T
}
}
}

我发现一个解决方案是使用 javaClass.kotlin对象引用上的扩展函数,以获取不变类型:
fun <T> foo(entry: T) {
with(entry.javaClass.kotlin) {
this // is instance of KClass<T>
}
}

这样,我既可以在运行时获得确切的类型,也可以使用该类型。

有趣的是,如果我使用父类(super class)型而不是泛型,使用后一种方法我仍然可以访问正确的类型,而无需变化:
class Derived: Base()

fun foo(entry: Base) {
with(entry.javaClass.kotlin) {
println(this == Derived::class)
}
}

fun main(args: Array<String>) {
val derived = Derived()
foo(derived) // prints 'true'
}

如果我猜对了, ::class等于调用java getClass ,它返回一个带有通配符的变体类型,而 javaClassgetClass强制转换为特定类型。
尽管如此,我还是不明白为什么我需要一个协变 KClass,因为它限制我只生成类型,因为还有其他方法可以在运行时访问确切的类并自由使用它,我想知道是否更多立即 ::class应该按设计返回一个不变的类型。

最佳答案

界内协方差的原因::class引用是,表达式被评估为的对象的实际运行时类型可能与表达式的声明或推断类型不同。

例子:

open class Base
class Derived : Base()

fun someBase(): Base = Derived()

val kClass = someBase()::class

表达式 someBase()键入为 Base ,但在运行时它是 Derived它被评估的对象。

打字 someBase()::class作为不变量 KClass<Base>根本不正确,事实上,计算这个表达式的实际结果是 KClass<Derived> .

为了解决这种可能的不一致(这会导致破坏类型安全),所有绑定(bind)的类引用都是协变的: someBase()::classKClass<out Base> ,这意味着在运行时 someBase()可能是 Base 的子类型,因此这可能是 Base 子类型的类标记.

当然,未绑定(bind)的类引用不是这种情况:当您使用 Base::class 时,你肯定知道它是 Base的类标记而不是它的某些子类型,所以它是不变的 KClass<Base> .

关于kotlin - 绑定(bind)类引用返回协变类型的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45782409/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com