¿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) } 
  • ¿Cómo get un KType en Kotlin?
  • La igualdad de class Kotlin falla
  • Cómo acceder a los objects-miembros de una statement de object en kotlin
  • ¿Cómo puedo get el nombre de una propiedad de Kotlin?
  • Interoperabilidad de reflexión de Kotlin con Java
  • String.intern () devuelve diferentes valores en un controller JDBC
  • ¿Cómo obtengo el valor de una propiedad con reflection?
  • Implementando una interfaz de kotlin en java
  • ¿Puedo usar kotlin.reflect para get un valor de un campo
  • Reflexión de Kotlin: compruebe si la propiedad tiene tipo
  • ¿Cómo get una KClass de Array?