1

I'm trying to write a method that will compare the 'common properties' (sharing the same name/type) of two objects in Kotlin. Its intended to be used in tests, for comparing 'expected' with 'actual' objects that aren't of the same type.

This is a simplified version on the code so far:

val obj1Props = obj1::class.memberProperties
val obj2Props = obj2::class.memberProperties

val commonPropertyPairs  = obj1Props.map { obj1Prop ->
        obj1Prop to obj2Props.find { obj2Prop -> obj1Prop.name == obj2Prop.name } }
    .filter { pair -> pair.second != null }

commonPropertyPairs.forEach { pair ->
  pair.first.get(obj1)
}

I'm currently getting this error message under 'pair.first.get' near the bottom:

out-projected type KProperty1<out Any, Any?> prohibits the use of public abstract fun get(receiver: T): R defined in kotlin.reflect.KProperty1

I understand that I obviously cannot use abstract methods, what should I be doing instead?

Morgan
  • 303
  • 2
  • 15

1 Answers1

2

Instead of obj1::class.memberProperties you need to use SomeClass::class.memberProperties, e.g.:

override fun buildNavItem() {
    val obj1 = "Hello"
    val obj2 = 10
    val obj1Props = String::class.memberProperties
    val obj2Props = Int::class.memberProperties

    val commonPropertyPairs  = obj1Props.map { obj1Prop ->
        obj1Prop to obj2Props.find { obj2Prop -> obj1Prop.name == obj2Prop.name } }
            .filter { pair -> pair.second == null }

    commonPropertyPairs.forEach { pair ->
        pair.first.get(obj1)
    }
}

The reason for this difference is that when using the SomeClass::class reference, it will necessarily be a class marker representing SomeClass, and not one of its possible derived classes, so it is KClass<SomeClass>without prediction types.

Sergio
  • 27,326
  • 8
  • 128
  • 149