如何用Kotlinreflection改变成员字段?

我正在从Java移植到Kotlin。 这个类声明了数百个对象。 每个对象都有一个名称属性,它与对象声明的variables名称相同。 Javareflection允许通过reflection使用声明的名称来设置对象成员name 。 只需要在数百个构造函数中保存一个参数。

我试图在Kotlin做同样的事情,但不知道如何做属性设置。 这里是一些简化的测试代码:

 package myPackage import kotlin.reflect.full.companionObject import kotlin.reflect.full.declaredMemberProperties class MyTestObject() { var name: String = "NotInitialized" companion object { val Anton = MyTestObject() val Berta = MyTestObject() val Caesar = MyTestObject() } } fun main(args : Array) { println(MyTestObject.Anton.name) // name not yet initialized // Initialize 'name' with the variable name of the object: for (member in MyTestObject::class.companionObject!!.declaredMemberProperties) { if (member.returnType.toString() == "myPackage.MyTestObject") { println("$member: ${member.name}") // Set 'name' property to 'member.name': // ??? } } println(MyTestObject.Anton.name) // now with the initialized name } 

??? 行是我想要访问MyTestObjectname属性, MyTestObject其设置为member.name 。 我正在寻找一个函数类似于(member.toObject() as MyTestObject).name = member.name

kotlin-reflection努力保持types安全的时候,有时候types系统和推理逻辑还不足以允许你以types安全的方式来做这些事情。 所以,你必须做出不加控制的强制转换,说明你对types的了解比编译器能够推断的更多。

在你的情况下,这是足够的MyTestObject member以便您可以传递伴侣对象实例到它的.get(...)并使用结果作为MyTestObject ,替换// ??? 符合:

 @Suppress("UNCHECKED_CAST") (member as KProperty1) .get(MyTestObject::class.companionObject!!.objectInstance!!) .name = member.name 

如果你可以替换MyTestObject::class.companionObject!!MyTestObject.Companion::class (即您的实际使用情况不涉及.companionObject ),未经检查的转换不需要,你可以用上面的语句替换上面的语句:

 (member.get(MyTestObject.Companion) as MyTestObject).name = member.name 

作为不需要伴随对象reflection的替代方法,您可以对委派执行相同的绑定逻辑。 实现provideDelegate允许你定制初始化属性的逻辑,这就是你可以指定名字的地方:

 operator fun MyTestObject.provideDelegate( thisRef: MyTestObject.Companion, property: KProperty<*> ) = apply { name = property.name } operator fun MyTestObject.getValue( thisRef: MyTestObject.Companion, property: KProperty<*> ) = this 

然后声明你的属性为

 val Anton by MyTestObject() val Berta by MyTestObject() val Caesar by MyTestObject() 

以下是基于热键解决方案的最终测试代码:

 package myPackage import kotlin.reflect.full.declaredMemberProperties class MyTestObject() { lateinit var name: String companion object { val Anton = MyTestObject() val Berta = MyTestObject() val Caesar = MyTestObject() init { for (member in MyTestObject.Companion::class.declaredMemberProperties) { if (member.returnType.toString() == "myPackage.MyTestObject") { (member.get(MyTestObject.Companion) as MyTestObject).name = member.name } } } } } fun main(args : Array) { println(MyTestObject.Anton.name) println(MyTestObject.Caesar.name) }