Как установить свойство val с отражением Kotlin? - PullRequest
0 голосов
/ 26 сентября 2018

Я хотел бы вернуть копию класса с другим значением, присвоенным свойству val.

data class Person(val name: String, val age: Int)

fun main() {
    val person = Person("Morné", 25)
    val property = person::class.declaredMemberProperties.first { it.name == "age" }
    person.copyWithValue(property.name, 22)
}

, если age было var, тогда я мог бы сделать это следующим образом:

fun main() {
    val person = Person("Morné", 25)
    val property = person::class.declaredMemberProperties.first { it.name == "age" }
    if (property is KMutableProperty<*>)
        property.setter.call(person, 22)
}

1 Ответ

0 голосов
/ 26 сентября 2018

Если вы действительно хотите вернуть только копию объекта, вы можете использовать copy, например:

fun main() {
  val person = Person("Morné", 25)
  val newPerson = person.copy(age = 22)
}

В противном случае, если вам действительно нужно отредактировать ageэто не должно быть val во-первых.Используя рефлексию, вы все равно можете адаптировать значение, но если ответов до этого уже достаточно, они являются подходящим способом ...

Для более динамичного способа вы можете использовать следующее (я все равно нацеливаюсь наcopy -метод, так как тогда вы не случайно обновите текущий объект):

val person = Person("Morné", 25)
val updates = mapOf("lastname" to "N/A", "age" to 22)

val copiedPerson = with(person::class.memberFunctions.first { it.name == "copy" }) {
  callBy(mapOf(instanceParameter!! to person)
      .plus(updates.mapNotNull { (property, newValue) ->
        parameters.firstOrNull { it.name == property }
            ?.let { it to newValue }
      })
  )
}
println(copiedPerson)

, который печатает:

Person(name=Morné, age=22)

Вы также можете использовать что-то вроде .let { person::class.cast(it } послеcallBy если вы хотите продолжить с фактического типа.Если вы хотите, чтобы это работало только с типом Person, вы также можете обменять person на Person и привести его непосредственно к as Person.

...