Вызовите класс данных 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
}


Другие вопросы по тегам