Вызовите класс данных copy() через отражение
Вот и все. Можно ли вызвать функцию copy() класса данных через отражение в Kotlin? Как я могу получить ссылку на саму функцию? Есть ли суперкласс для всех классов данных? (Я не могу найти это...)
1 ответ
Там нет общего супертипа для всех data
классы.
В принципе, copy
является обычной функцией-членом, которую вы можете вызвать с помощью API-интерфейса Kotlin:
val person = Person("Jane", 23)
val copy = person::class.memberFunctions.first { it.name == "copy" }
val instanceParam = copy.instanceParameter!!
val ageParam = copy.parameters.first { it.name == "age" }
val result = copy.callBy(mapOf(instanceParam to person, ageParam to 18))
println(result) // Person(name=Jane, age=18)
Убедитесь, что вы добавили kotlin-reflect
как зависимость.
В приведенном выше примере показано, как можно пропустить значения для параметров по умолчанию - значение не передается для name
, Если вы хотите передать все параметры, это можно сделать более простым способом:
val person = Person("Jane", 23)
val copy = person::class.memberFunctions.first { it.name == "copy" }
val result = copy.call(person, person.name, 18)
println(result) // Person(name=Jane, age=18)
API отражения Kotlin не обязательно вызывать функцию, если вы передаете аргументы для всех параметров, вы также можете сделать это с помощью отражения Java:
val person = Person("Jane", 23)
val copy = person::class.java.methods.first { it.name == "copy" }
val result = copy.invoke(person, person.name, 18)
println(result) // Person(name=Jane, age=18)
Итак, на основе ответа hotkey выше:
fun <T : Any> clone (obj: T): T {
if (!obj::class.isData) {
println(obj)
throw Error("clone is only supported for data classes")
}
val copy = obj::class.memberFunctions.first { it.name == "copy" }
val instanceParam = copy.instanceParameter!!
return copy.callBy(mapOf(
instanceParam to obj
)) as T
}