Default Types for Generics

I could not find an existing topic regarding this issue but maybe my keywords were simply not the right ones to search for. Regardless, here it comes.

I would love to see default types for generics in Kotlin like Rust has it:

The most prominent example that could make use of this would be Comparable<T> by changing it to Comparable<T = this> but there are more interesting use cases.

sealead class S
class A : S()
class B : S()

open class X<T : A>
class Y : X<B>()

Constructing X is not possible without specifying the concrete type right now, hence, one has to write X<A>() everywhere. This is cumbersome and repetitive and something that was clear for X from the very beginning.

open class X<T : A = A>
class Y() : A<B>()

Now it is possible to construct X without specifying A everywhere: X()

4 Likes
4 Likes

I didn’t expect that that topic would contain the same problem judging from the title.

Sorry to bug you but are there any updates on this? This would be amazing. Also, is there an official youtrack issue I can follow? Thanks.

Based on this post here I guess that this is something that will be part of 1.4 or will be implemented in one of the 1.4.x releases. I haven’t seen it talked about as part of 1.4 so probably not the first release.

1 Like

Any news on this feature?

Its 2021 and I still see occasional need for such default generics. any updates on this?

best regards

You don’t need a language feature for that:

class MyClass<T> {

    companion object {
        operator fun invoke() = MyClass<Int>()
    }

}


fun main() {
    val foo = MyClass<String>()
    val bar = MyClass() // this is a MyClass<Int>
}
1 Like

I don’t know Rust or any other language with this feature, but I guess this is not only about initializing and object. You still can’t do e.g.:

interface Foo {
    val myObj: MyClass
}
1 Like

Use a default using a typealias:

class MyClass<T> {

    companion object {
        operator fun invoke() = MyClass<Int>()
    }

}

typealias MyClassInt = MyClass<Int>

interface Foo {
    val myObj: MyClassInt
}

But actually, why do you need that in the first place?

In my case I have a ViewModel Class that accepts an inputDataAdapter so that a ViewModel for a specific view can provide a TypeAdapter from String to “T”. But in some or many cases a simple (String) → String inputDataAdapter could be provided as Default Lambda.

The only way that I figured out is to “dirty” cast to T. If I could provide a Default Type for “T” the dirty cast is no more needed.

class ViewModel<T: DA = String>(
    val inputDataAdapter: (String) -> DA = { input -> input },
)

// instead of

class ViewModel<T>(
    val inputDataAdapter: (String) -> T = { input -> input as T },
)