Creating generic Kotlin class and operating with template parameter inside

Hi All.

I learns Kotlin… after C++ and some language feature are not trivial for me because I still think in C++ paradigms.
So… the question is next:

I have some different class. All of them MUST have static function “create”.
For example: class A { companion object { fun create( ): A { … } } }

And I want to implement next generic class:
class Test< TYPE >
{
private var mValue: T? = null

fun initialize( ) { mValue = T.create( ) }
}

… to have a possibility to do like this:
var test: Test< A > = Test< A >( )
test.initialize( )

As you know this leads to error in Kotlin. But this is possible in C++ and if you put in template parameter some other class what haven’t got “create” you will have compilation error.

Is it possible to do the same in Kotlin? If yes, how?

It’s not possible to do the same in Kotlin because at run time all information about T is lost, so when you write T.create() the run time has no idea what is T.

What is the right way to do what you want really depends on what Test does. My suggestion is to just make the constructor of Test take an instance of T.

(By the way if you really want to do what you’re asking you can, take a Class<T> object in Test's constructor and use reflection to invoke create using reflection, in that case you won’t know if your class has create until your code runs).

To add on to this, you need to guarantee T has create(): T, so you would either create an interface (best idea imo) or an open/abstract class.

interface Creates<T> {
    fun create(): T
}

And like he said, you will need an instance of T to actually use create, because the interface itself does not provide a concrete implementation of create, just the information that whatever implements this interface has to implement create

class Test<T: Creates<T>>(private val impl: T) {
    lateinit var mValue: T
    fun initialize() { mValue = impl.create() }
}

and here is where i like to use inline fun with reified parameters because it can take away the ugly call of Test(A::class)

inline fun <reified T: Creates<T>> Test(): Test<T> = Test(T::class)

so in the end:

var test = Test<A>()
test.initialize()

works just as expected

1 Like

KClass<T> does not have a create method, even if T does. If you want to create a T, you can pass in a () -> T parameter.

1 Like

Yes that is what I meant, my bad. I think I got a little carried away in the latter half of my post