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
?
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.
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.
We can make generic variable using this kind of syntax: "val destinationActivity: Class<*>".
Generic functions Type parameters are placed before the name of the function: fun <T> singletonList(item: T): List<T> { // ... } fun <T> T.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With