reflection - 如何通过反射在 Kotlin 中设置伴生对象的属性?

标签 reflection kotlin

当我有一个类有一个伴生对象时,是否可以使用反射在这个伴生对象中设置一个属性?我可以使用普通属性来做到这一点,但在伴随对象上失败:

import kotlin.reflect.KMutableProperty
import kotlin.reflect.full.companionObject
import kotlin.reflect.full.memberProperties

class WithProperty {
    lateinit var prop: String

    companion object {
        lateinit var companionProp: String
    }

    fun test() = "$companionProp $prop"
}

fun main(args: Array<String>) {
    val obj = WithProperty()

    val prop = obj::class.memberProperties.filter { it.name == "prop" }.first()
    if (prop is KMutableProperty<*>) {
        prop.setter.call(obj, "world")
    }

    val companion = obj::class.companionObject
    if (companion != null) {
        val companionProp = companion.memberProperties.filter { it.name == "companionProp" }.first()
        if (companionProp is KMutableProperty<*>) {
            companionProp.setter.call(companionProp, "hello") // <-- what must go here as first argument?
        }
    }

    println(obj.test())
}

调用 normal 属性的 setter 可以正常工作,但是当我调用 companionProp.setter.call(companionProp, "hello") 时,我得到了

Exception in thread "main" java.lang.IllegalArgumentException: object is not an instance of declaring class

我必须将什么作为第一个参数传递给 call() 才能成功?

编辑:我将 companionProp 写为第一个参数,但这绝对是错误的,我实际上尝试使用 companion 对象,但那是效果不佳。

最佳答案

object is not an instance of declaring class

就像在Java中一样,调用反射方法时需要将对象本身作为第一个参数传递。

call 的第一个参数应该是伴随对象,因为这是您要修改其属性的对象。

您传递的是同伴的类对象,而不是同伴对象本身。

伴生对象可以通过 ClassName.Companion 访问,或者在使用进一步反射时,通过 KClass#companionObjectInstance .

companionProp.setter.call(WithProperty.Companion, "hello")
companionProp.setter.call(obj::class.companionObjectInstance, "hello")
companionProp.setter.call(WithProperty::class.companionObjectInstance, "hello")

运行时,两个变体都按预期打印 hello world

请记住,如果伴随对象不存在,Foo.Companion 将导致编译错误,而反射变体将返回 null

关于reflection - 如何通过反射在 Kotlin 中设置伴生对象的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45056702/

相关文章:

android - 在Kotlin中将日期时间字符串(2018-04-13T20 :00:00. 0400)转换为日期字符串(April 13, 2018)

java - 使用反射从对象获取数组列表大小

c# - 并非所有程序集都从 bin 文件夹加载到 AppDomain

c# - 从未知对象获取属性和值

java - 如何使用外部 java 库在命令行中编译和运行 kotlin 程序

android - 如何将包含数组的模型发布到 retrofit 车身发布中?

android - ReToucherView的onTouchListener已禁用其滚动

c# - 是否有从表达式树或 CodeDOM 转换为 Reflection.Emit 的库?

c# - 如何使用反射动态设置事件处理程序

android - Android compileTarget P appcompat库