Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you have a generic primary constructor in Kotlin?

This would work:

class Generic<T, R>(thingy: R)
{
    val x = thingy.getX()
}

But the parameter R should really not be a part of the class signature. It is relevant only at construction time. The same way a type parameter of a generic method has nothing to do with the type parameters of the class.

However, this does not work:

class Generic<T>(thingy: R)
{
    val x = thingy.getX()
}

neither does this:

class Generic<T><R>(thingy: R)
{
    val x = thingy.getX()
}

and I did not find the answer in the documentation.

like image 697
Martin Drozdik Avatar asked Mar 07 '23 09:03

Martin Drozdik


1 Answers

That is not possible directly.

You can however achieve a desired result by using a factory method:

interface HasX<out V> {
    val x: V
}

class Generic<T>(val x: Int) {
    companion object {
        fun <T, R : HasX<Int>> create(thingy: R) = Generic<T>(thingy.x)
    }
}

val result: Generic<String> = Generic.create(object : HasX<Int> {
    override val x: Int = 12
})

Typically factory methods start with lower case ( e.g. mutableList) there is nothing stopping you from doing it differently:

fun <T, X : HasX<Int>> Generic(thingy: X):Generic<T> = Generic(thingy.x)

val result: Generic<String> = Generic(object : HasX<Int> {
    override val x: Int = 12
})

As noted by @Alexey Romanow parts of the Kotlin stdlib use this approach.

like image 198
miensol Avatar answered Mar 27 '23 19:03

miensol