Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get generic param class in Kotlin?

Tags:

kotlin

I need to be able to tell the generic type of kotlin collection at runtime. How can I do it?

val list1 = listOf("my", "list")
val list2 = listOf(1, 2, 3)
val list3 = listOf<Double>()

/* ... */

when(list.genericType()) {
    is String -> handleString(list)
    is Int -> handleInt(list)
    is Double -> handleDouble(list)
}
like image 576
pawelo Avatar asked Apr 03 '17 12:04

pawelo


People also ask

How do I get the generic class for Kotlin?

There are no direct ways to do this in Kotlin. In order to check the generic type, we need to create an instance of the generic class<T> and then we can compare the same with our class.

How do you provide a generic parameterized type?

In order to use a generic type we must provide one type argument per type parameter that was declared for the generic type. The type argument list is a comma separated list that is delimited by angle brackets and follows the type name. The result is a so-called parameterized type.

How do you find the type of generic class?

You can get around the superfluous reference by providing a generic static factory method. Something like public static <T> GenericClass<T> of(Class<T> type) {...} and then call it as such: GenericClass<String> var = GenericClass. of(String. class) .


1 Answers

Kotlin generics share Java's characteristic of being erased at compile time, so, at run time, those lists no longer carry the necessary information to do what you're asking. The exception to this is if you write an inline function, using reified types. For example this would work:

inline fun <reified T> handleList(l: List<T>) {
    when (T::class) {
        Int::class -> handleInt(l)
        Double::class -> handleDouble(l)
        String::class -> handleString(l)
    }
}

fun main() {
    handleList(mutableListOf(1,2,3))
}

Inline functions get expanded at every call site, though, and mess with your stack traces, so you should use them sparingly.

Depending on what you're trying to achieve, though, there's some alternatives. You can achieve something similar at the element level with sealed classes:

sealed class ElementType {
    class DoubleElement(val x: Double) : ElementType()
    class StringElement(val s: String) : ElementType()
    class IntElement(val i: Int) : ElementType()
}

fun handleList(l: List<ElementType>) {
    l.forEach {
        when (it) {
            is ElementType.DoubleElement -> handleDouble(it.x)
            is ElementType.StringElement -> handleString(it.s)
            is ElementType.IntElement -> handleInt(it.i)
        }
    }
}
like image 145
pdpi Avatar answered Oct 19 '22 02:10

pdpi