Generic Kotlin Type Parameters

In 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 addInt and addAnotherInt take a contravariant MutableList of Number as an argument. But with the main function, one line compiles fine, and the other doesn't.

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

What could be the difference between addInt and addAnotherInt ?

+5
source share
2 answers

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

In simple words, you stated that your addAnotherInt() wants a list that is at least generic, like receiving any type of Number .

Unlike addInt , item: T and list: MutableList<in T> declared. T itself is declared as a free type variable for a function, which means that it will be bound to each specific call site. Therefore when you say

 addInt(4, mutableIntList) 

Kotlin associates T with Int based on the first argument and passes it to the second argument, which is now MutableList<in Int> . You passed in a MutableList<Int> , which is compatible with this type, so Kotlin is satisfied.

If you announced

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

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

+7
source

Your code will be compiled using a list of numbers:

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

But since the type is inferred to a MutableList<Int> , you cannot use it as a MutableList<in Number> . MutableList<? super Number> this mean Java equivalent MutableList<? super Number> MutableList<? super Number> and means that you can add any Number to the list. But adding a Long to a MutableList<Int> not possible.

The second addInt() method is a bit more strict and translates MutableList<? super Int> MutableList<? super Int> in your usecase. That way you can use it as such. Both methods can use a MutableList<Number> , though.

+2
source

Source: https://habr.com/ru/post/1275123/


All Articles