I am not able to make this simple example of code work:
package com.example
import kotlin.reflect.full.memberProperties
fun main() {
val person = Person("Alice", 29)
person::class.memberProperties.forEach {
println("${it.name} = ${it.get(person)}")
}
}
data class Person(val name: String, val age: Int)
It should print the list of properties with their values but when executed it throws exception:
Argument type mismatch: actual type is 'com.example.Person', but 'CapturedType(out com.example.Person)' was expected.
I am not able to make this simple example of code work:
package com.example
import kotlin.reflect.full.memberProperties
fun main() {
val person = Person("Alice", 29)
person::class.memberProperties.forEach {
println("${it.name} = ${it.get(person)}")
}
}
data class Person(val name: String, val age: Int)
It should print the list of properties with their values but when executed it throws exception:
Argument type mismatch: actual type is 'com.example.Person', but 'CapturedType(out com.example.Person)' was expected.
1 Answer
Reset to default 1You should use Person::class
instead of person::class
. The latter gives you a KClass<out Person>
. From the compiler's point of view, KClass<out Person>
can represent a subclass of Person
too. This means memberProperties
may contain properties exclusive to that (unknown) subclass. Therefore, it is not safe to pass a Person
to it.get
, because it
might not be a property that the instance of Person
has.
Of course, in reality Person
cannot have subclasses. If you cannot hardcode Person::class
(because you do not know the runtime type of person
at compile time for some reason), you can use an unchecked cast to convince the compiler.
(person::class as KClass<Any>).memberProperties.forEach {
println("${it.name} = ${it.get(person)}")
}