如何使用 Kotlin 反射设置 val 属性?
How to set val property with Kotlin reflection?
我想 return 一份 class 的副本,将不同的值分配给 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)
}
如果你真的想return只是对象的一个副本,你可以使用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)
如果您想继续使用实际类型,也可以在 callBy
之后使用类似 .let { person::class.cast(it }
的内容。如果您只希望它与 Person
类型一起使用,您还可以将 person
与 Person
交换并将其直接转换为 as Person
.
我想 return 一份 class 的副本,将不同的值分配给 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)
}
如果你真的想return只是对象的一个副本,你可以使用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)
如果您想继续使用实际类型,也可以在 callBy
之后使用类似 .let { person::class.cast(it }
的内容。如果您只希望它与 Person
类型一起使用,您还可以将 person
与 Person
交换并将其直接转换为 as Person
.