This is a contrived example for the sake of my understanding Kotlin language.
The class Box<T> below models a box that contains boxes of the same type T.
The question is why arr += x causes compile error while arr.add(x) does not.
The error message is:
Type mismatch. Required: kotlin.collections.ArrayList<Box>
Found: List<Box>
the property arr is immutable and points to a mutable list. So I believe there is no ambiguity whether arr += x should mean arr = arr + x or arr.add(x). It should mean arr.add(x)
I also noticed that the issue is gone if generic type Box implements Iterable<T> instead of Iterable<Box<T>>
So, what is the reason of the error?
class Box<T>(private val arr: ArrayList<Box<T>> = ArrayList()) : Iterable<Box<T>> {
private val id: Int = seq++
override operator fun iterator(): Iterator<Box<T>> {
return object : Iterator<Box<T>> {
private var i = 0;
override fun hasNext(): Boolean {
return i < arr.size
}
override fun next(): Box<T> {
return arr[i++]
}
}
}
fun add(x: Box<T>) {
// arr.add(x) // OK
arr += x // Error: Type mismatch.
}
companion object {
var seq: Int = 0
}
override fun toString(): String {
return "Box[$id]"
}
}
fun main() {
val box = Box<Int>(arrayListOf(Box(), Box()))
for (x in box) {
println(x)
}
}
arr += xis neitherarr = arr + x(though it could be in other cases) norarr.add(x)(not directly, at least). It is just a call to theplusAssignoperator function.There are many overloads of
plusAssign. The relevant ones to this question are:The first overload would call
arr.add(x), and the second would callarr.addAll(x).The problem is, both of these are applicable in your case, but there is no "most specifc" overload among them.
The first overload is trivially applicable, and the second overload is applicable because
xis also aIterable<Box<T>>because of the interface implementation.None of these are more specific because none of them can "forward" the call to the other. An overload is the most specific if it is the single overload that can "forward" to all the other applicable overloads. In this case:
See also the Kotlin Language Specification.
I would just call
addmanually to fix the error, instead of using operators.