0

I would like to return a copy of a class with a different value assigned to a val property.

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)
}

if age was a var then I could do it like follows:

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)
}
4

1 回答 1

3

如果您真的只想返回对象的副本,可以使用copy,例如:

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

否则,如果你真的必须编辑age它,它首先不能是 a 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 }after之类的东西。callBy如果您只希望它与Person您也可以交换的类型person一起使用Person并将其直接转换为as Person.

于 2018-09-26T08:00:30.477 回答