Reputation: 1881
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
?
Upvotes: 6
Views: 1633
Reputation: 200266
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.
Upvotes: 10
Reputation: 39873
Your code will compile with a number list:
val mutableIntList = mutableListOf<Number>(1, 2, 3)
But since the type is inferred to MutableList<Int>
, you can't use it as a MutableList<in Number>
. This translates to the Java equivalent MutableList<? super Number>
and means that you can add any Number
to the list. But adding a Long
to the MutableList<Int>
is not possible.
Your second method addInt()
is a little more strict and translates MutableList<? super Int>
in your usecase. Thus you can use it as such. Both methods are capable of using a MutableList<Number>
though.
Upvotes: 2