Get property with instanced type parameters


#1

Hi, I’m in this situation

import kotlin.reflect.full.declaredFunctions

class A<B> {
  var p: B? = null
}
interface X {
  fun a(): A<Int>
}

fun main(args: Array<String>) {
  val aint = X::class.declaredFunctions.first().returnType
}

is there some way to get the type of the p property of class A with the Int parameter from the KType aint? I imagine I can compute it myself by getting the KClass of aint, getting the declared props and then matching the type parameters in the property type with the ones in aint, but it seems a somewhat involved, error prone, process


#2

Type parameters are erased in runtime, so no it is not possible at all. The only way is to store the type in a separate field like

class A<B>(val type: KClass<B>) {
  var p: B? = null
}

#3

I thought Kotlin stored additional information in the class file because

fun main(args: Array<String>) {
  val aint = X::class.declaredFunctions.first().returnType
  println(aint)
}

prints

A<kotlin.Int>

So the instanced type parameter of the return type is available at runtime


#4

Not always. In this case you have so-called reified type. It is not stored, but defined in the call-site and then inlined. In your particular case it works because the type of X is defined statically and compiler can infer it. In more general case it won’t work.

In case reification is available, you can find type via reification directly:

  inline <reified B> fun getType(): KClass<out B> = B::class

#5

I don’t see how it would be able to inline that in my case, after .first() the compiler should have no clue of what function I’m talking about at the definition of aint.

Anyway, however it’s done, since aint is A<Int> at runtime, getting the type of A::p as Int? when starting from aint, instead of the erased B?, should be a matter of matching names and “filling in” the slots.