Search code examples
genericskotlinkotlin-reified-type-parameters

Calling a fun with reified type parameter if you just have a KClass object?


One can only use reified type parameters with inline functions. So if I want such a parameter for a class I need a trick like this:

class Foo<T : Any>(private val clazz: KClass<T>) {
    companion object {
        inline fun <reified T: Any> create() = Foo(T::class)
    }
}

I can then create instances of Foo like this:

val foo = Foo.create<Bar>()

Within Foo I have access clazz but my question is can I then use clazz when I need to call methods that require a reified type parameter`?

E.g. within Foo I'd like to add a method like this:

fun print(list: List<Alpha>) {
    list.filterIsInstance<T>().forEach { print(it) }
}

But as far as I can see there's no way to get from clazz to something I can use as a type parameter here.

And yes, I know there's a form of filterIsInstance that takes a Class so I can do:

list.filterIsInstance(clazz.java).forEach { print(it) }

However many libraries contain methods where both forms (explicit class parameter and reified type parameter) are not provided.

E.g. the Jackson Kotlin Extensions.kt. Actually this isn't a great example as the non-reified equivalents are all one-liners but this isn't always the case - then you end up unpacking the implementation of the reified-type-parameter method into your code.


Solution

  • no, because those functions are inline, they are inlined at compiletime and a Class or KClass is using reflection at runtime

    there are some tricks that you can do.. like with the companion class, but that does nto need the KClass<T> at all.. anything else that provides a generic argument of T would work just as well for the reified type info

    PS: reflection also cannot help you reliably because inline functions do not really exist at runtime, as explained by their modifier inline