kotlin:列出任何对象的属性 - 方差错误

时间:2018-04-03 14:35:46

标签: kotlin covariance

我正在尝试编写一个函数,为任何类型生成属性和值的映射

inline fun <reified T : Any> T.propertiesMap() {
    for (property in this::class.memberProperties) {
        property.get(this)
    }
}

我在property.get(this)中遇到了关于

的编译错误
  

out-projection类型[...]禁止使用'public abstract fun get(接收器......

2 个答案:

答案 0 :(得分:2)

问题是,this::class会产生KClass<out T>而不是KClass<T>,这是在T来电中使用property.get(...)类型的任何内容所需要的。所以你可以做一个未经检查的演员来做你想做的事情:

fun <T : Any> T.propertiesMap() {
    @Suppress("UNCHECKED_CAST")
    for (property in (this::class as KClass<T>).memberProperties) {
        property.get(this)
    }
}

这不需要函数是内联函数或者是reified类型参数。否则,您可以将功能更改为使用T::class而不是this::class来创建匹配的KClass<T>

inline fun <reified T : Any> T.propertiesMap() {
    for (property in T::class.memberProperties) {
        property.get(this)
    }
}  

答案 1 :(得分:1)

如果您使用的是您正在进行修改的类型而不是该类型的实例,则方差问题将会消失。当您致电T::class.memberProperties时,您会收到Collection<KProperty<T, *>>,这是我认为您想要的。另一方面,如果您在实例(this)上调用该内容而不是类型,则会返回Collection<KProperty<out T, Any?>>,这是您的外部差异问题的来源。

inline fun <reified T : Any> T.propertiesMap() {
    for (property in T::class.memberProperties) {
        property.get(this)
    }
}

基本上,您需要执行T::class而不是this::class才能获得正确的收集。我已经将您的代码保留为原样,否则因为我不清楚您希望此功能执行什么操作,但我怀疑您可以放弃for循环以支持map调用。< / p>