saiedmomen
saiedmomen

Reputation: 1441

obtain class from nested type parameters in kotlin

I have a val built like this

val qs = hashMapOf<KProperty1<ProfileModel.PersonalInfo, *> ,Question>()

How can I obtain the class of ProfileModel.PersonalInfo from this variable?

In other words what expression(involving qs of course) should replace Any so that this test passes.

@Test
fun obtaionResultTypeFromQuestionList(){
    val resultType = Any()
    assertEquals(ProfileModel.PersonalInfo::class, resultType)
}

Thank you for your attention

Upvotes: 1

Views: 711

Answers (1)

hluhovskyi
hluhovskyi

Reputation: 10106

There is no straight way to get such information due to Java type erasure. To be short - all information about generics (in your case) is unavailable at runtime and HashMap<String, String> becomes HashMap.

But if you do some changes on JVM-level, like defining new class, information about actual type parameters is kept. It gives you ability to do some hacks like this:

val toResolve = object : HashMap<KProperty1<ProfileModel.PersonalInfo, *> ,Question>() {
    init {
        //fill your data here
    }
}

val parameterized = toResolve::class.java.genericSuperclass as ParameterizedType
val property = parameterized.actualTypeArguments[0] as ParameterizedType
print(property.actualTypeArguments[0])

prints ProfileModel.PersonalInfo.

Explanation:

  1. We define new anonymous class which impacts JVM-level, not only runtime, so info about generic is left
  2. We get generic supperclass of our new anonymous class instance what results in HashMap< ... , ... >
  3. We get first type which is passed to HashMap generic brackets. It gives us KProperty1< ... , ... >
  4. Do previous step with KProperty1

Kotlin is tied to the JVM type erasure as well as Java does. You can do a code a bit nice by moving creation of hash map to separate function:

inline fun <reified K, reified V> genericHashMapOf(
        vararg pairs: Pair<K, V>
): HashMap<K, V> = object : HashMap<K, V>() {
    init {
        putAll(pairs)
    }
}

...

val hashMap = genericHashMapOf(something to something)

Upvotes: 4

Related Questions