Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin Generics type parameters

At the following source code

fun main(args: Array<String>) {
    println("Hello, world!")

    val mutableIntList = mutableListOf(1, 2, 3)

    addInt(4, mutableIntList) // No compile-time error
    addAnotherInt(5, mutableIntList) // Compile-time error

    println(mutableIntList)

}

fun <T: Number> addInt(item:T,
                       list:MutableList<in T>){
    list.add(item)
}

fun <T: Number> addAnotherInt(item:T,
                              list:MutableList<in Number>){
    list.add(item)
}

The functions addInt and addAnotherInt take as an argument a contravariant MutableList of Number. But at the main function one line compiles normally and the other is not.

I also checked the generated java code from these functions and they seem identical.

What could be the difference between the functions addInt and addAnotherInt?

like image 724
LiTTle Avatar asked Feb 02 '18 10:02

LiTTle


People also ask

What is type parameter in Kotlin?

The type parameter lets you specify exactly that—instead of “This variable holds a list,” you can say something like “This variable holds a list of strings.” Kotlin's syntax for saying “a list of strings” looks the same as in Java: List<String> . You can also declare multiple type parameters for a class.

How can I check for generic type in 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 declare a generic variable in Kotlin?

We can make generic variable using this kind of syntax: "val destinationActivity: Class<*>".

How do you write generic method Kotlin?

Generic functions Type parameters are placed before the name of the function: fun <T> singletonList(item: T): List<T> { // ... } fun <T> T.


1 Answers

in Number means "Number or its supertype". Int is not a "Number or its supertype", it is its subtype.

In plain words, you declared that your addAnotherInt() wants a list that is at least as general as accepting any kind of Number.

By contrast, addInt declares item: T and list: MutableList<in T>. T itself is declared as a free type variable for the function, which means it will be bound at each specific call site. So when you say

addInt(4, mutableIntList)

Kotlin binds T to Int based on the first argument and propagates this to the second argument, which is now MutableList<in Int>. You passed in a MutableList<Int> which is compatible with that type, so Kotlin is satisified.

If you declared

val mutableIntList: MutableList<Number> = mutableListOf(1, 2, 3)

then the code would compile because now the list is as general as required, and you can add any Number to it.

like image 74
Marko Topolnik Avatar answered Sep 20 '22 01:09

Marko Topolnik