mardi 1 février 2022

How do I get all properties from an arbitrary Kotlin object?

This is another Kotlin oddity I've run into.

I had this code:

TableCharsets::class.declaredMemberProperties.asSequence()
    .map { p -> p.get(TableCharsets) }

and it worked fine.

Then I wanted to do it for more than one object in a loop. So I thought I could write this:

sequenceOf(TableCharsets, Iso2022Charsets, EucCharsets, ShiftJisCharsets).forEach { obj ->
    obj::class.declaredMemberProperties.asSequence()
        .map { p -> p.get(obj) }
}

But the compiler complains about the call to p.get(obj).

And indeed, if I write this:

val obj = TableCharsets
obj::class.declaredMemberProperties.asSequence()
    .map { p -> p.get(obj) }

This gives the same error. Apparently p.get(R) takes Nothing, so there is no possible object I can pass in which would be acceptable.

Thinking that maybe I lost the type of the object somehow, I tried extracting to a function so that it had a known but generic type:

fun <T: Any> extract(obj: T): Sequence<Any> {
    obj::class.declaredMemberProperties.asSequence()
        .map { p -> p.get(obj) }
}

Again, I get the error that p.get(R) only takes Nothing, and won't let me pass in a T.

When I hover over declaredMemberProperties, IDEA says that it returns a Collection<KProperty<T, *>>, but somehow the property p inside my lambda is a KProperty1<out Any, *>, so that's surely the problem. But it makes no sense to me right now how it is getting that type.

How can I make this work?





Aucun commentaire:

Enregistrer un commentaire