¿Cómo cambiar un campo de miembro con la reflexión de Kotlin?

Estoy portando una class de Java a Kotlin. Esta class declara cientos de objects. Cada object tiene una propiedad de nombre que es idéntica al nombre de la variable declarada del object. La reflexión de Java permite usar el nombre declarado a través de la reflexión para establecer el name miembro del object. Solo guarda un parámetro en cientos de constructores.

Intento hacer lo mismo en Kotlin, pero no puedo entender cómo configurar la propiedad. Aquí hay algunos códigos de testing simplificados:

 package myPackage import kotlin.reflect.full.companionObject import kotlin.reflect.full.declanetworkingMemberProperties 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!!.declanetworkingMemberProperties) { 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 } 

??? El ??? línea es donde me gustaría get acceso a la propiedad del name de MyTestObject para establecerlo en member.name . Estoy buscando una function similar a (member.toObject() as MyTestObject).name = member.name .

Mientras que kotlin-reflection esfuerza por ser seguro para types, a veces el sistema de tipo y la lógica de inferencia no son suficientes para permitir cosas como lo que estás tratando de hacer de una manera segura. Por lo tanto, debe realizar conversiones sin marcar, indicando que su conocimiento sobre los types es más de lo que el comstackdor puede inferir.

En su caso, es suficiente .get(...) member para que pueda pasar la instancia del object compañero a su .get(...) y usar el resultado como MyTestObject , replace el // ??? linea con:

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

Si puede replace MyTestObject::class.companionObject!! con MyTestObject.Companion::class (es decir, su caso de uso real no implica get .companionObject de diferentes classs), el molde sin .companionObject no es necesario, y puede replace la statement anterior con esto:

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

Como una alternativa que no requiere reflexión de object complementario, puede hacer la misma lógica de enlace con la delegación. La implementación de provideDelegate permite personalizar la lógica de initialization de la propiedad, y allí es donde puede asignar los nombres:

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

Luego declare sus properties como

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

Aquí está el código de testing final basado en la solución de teclas de acceso directo:

 package myPackage import kotlin.reflect.full.declanetworkingMemberProperties class MyTestObject() { lateinit var name: String companion object { val Anton = MyTestObject() val Berta = MyTestObject() val Caesar = MyTestObject() init { for (member in MyTestObject.Companion::class.declanetworkingMemberProperties) { if (member.returnType.toString() == "myPackage.MyTestObject") { (member.get(MyTestObject.Companion) as MyTestObject).name = member.name } } } } } fun main(args : Array<String>) { println(MyTestObject.Anton.name) println(MyTestObject.Caesar.name) } 
  • Kotlin: ¿Es aquí una forma inteligente de lanzar NotImplementedError para todos los methods de una class?
  • ¿Cómo hacer inferencia tipo Kotlin desde la reflexión KClass?
  • String.intern () devuelve diferentes valores en un controller JDBC
  • Kotlin: isAssignableFrom y reflexiones del tipo de reflexión
  • Reflexión de KFlin KFunction - get valores de parameters
  • ¿Cómo obtengo una KProperty1 de una KProperty0?
  • ¿Cómo puedo get el nombre de una propiedad de Kotlin?
  • Manera idiomática de invocar methods a través de la reflexión en Kotlin
  • Kotlin: doble operador de colon (reflexión) sobre
  • Interoperabilidad de reflexión de Kotlin con Java
  • ¿Por qué == e iguales producen resultados diferentes?