gpt4 book ai didi

reflection - 如何使用 Kotlin 反射更改成员字段?

转载 作者:行者123 更新时间:2023-12-04 17:31:47 27 4
gpt4 key购买 nike

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

我尝试在 Kotlin 中做同样的事情,但不知道如何进行属性设置。下面是一些简化的测试代码:

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<String>) {
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
}
???行是我想访问 name 的地方 MyTestObject 的属性(property)将其设置为 member.name .我正在寻找类似于 (member.toObject() as MyTestObject).name = member.name 的函数.

最佳答案

kotlin-reflection努力实现类型安全,有时类型系统和推理逻辑不足以允许您以类型安全的方式尝试执行的操作。因此,您必须进行未经检查的强制转换,说明您对类型的了解超出了编译器可以推断的范围。

在你的情况下,投 member 就足够了这样您就可以将伴随对象实例传递给它的.get(...)并将结果用作 MyTestObject , 替换 // ???符合:

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

如果可以更换 MyTestObject::class.companionObject!!MyTestObject.Companion::class (即您的实际用例不涉及从不同的类获取 .companionObject),不需要未经检查的强制转换,您可以将上面的语句替换为:
(member.get(MyTestObject.Companion) as MyTestObject).name = member.name

作为根本不需要伴随对象反射的替代方案,您可以对委托(delegate)执行相同的绑定(bind)逻辑。 Implementing 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()

关于reflection - 如何使用 Kotlin 反射更改成员字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46847345/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com