当我有一个具有伴随对象的类时,是否可以使用反射在此伴随对象中设置属性?我可以使用普通属性来执行此操作,但在随播对象上失败:
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())
}
调用普通属性的setter可以正常工作,但是当我调用companionProp.setter.call(companionProp, "hello")
时,我得到了
线程“main”中的异常java.lang.IllegalArgumentException:object不是声明类的实例
我必须作为第一个参数传递给call()
才能成功?
编辑:我写了companionProp
作为第一个参数,但这肯定是错误的,我实际上尝试使用companion
对象,但这样做也不行。< / p>
答案 0 :(得分:3)
object不是声明类
的实例
就像在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
。
答案 1 :(得分:2)
第一个参数是声明类的实例。
您传递的是KProperty
实例companionProp
而不是同伴对象实例。但是,您可以使用KClass.companionObjectInstance
获取公司实例。例如:
//a non-static property having a receiver, so it should be a KMutableProperty1 here
// v
if (companionProp is KMutableProperty1<*, *>) {
// get the companion object instance ---v
companionProp.setter.call(obj::class.companionObjectInstance, "hello")
}