如何用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 }
该???
行是我想要访问MyTestObject
的name
属性, 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) }