Scala covariant doc example allows apples and oranges
A mutable list cannot/should not be covariant in its argument type. Exactly because of the reason you noted.
Suppose, you could have a MutableList[Orange]
, that was a subclass of a MutableList[Fruit]
. Now, there is nothing that would prevent you from making a function:
def putApple(fruits: MutableList[Fruit], idx: Int) =
fruits(idx) = new Apple
You can add Apple
to the list of Fruits
, because Apple
is a Fruit
, nothing wrong with this.
But once you have a function like that, there is no reason you can't call it like this:
val oranges = new MutableList[Orange](new Orange, new Orange)
putApple(oranges, 0)
This will compile, since MutableList[Orange]
is a subclass of MutableList[Fruit]
. But now:
val firstOrange: Orange = oranges(0)
will crash, because the first element of oranges
is actually an Apple
.
For this reason, mutable collections have to be invariant in the element type (to answer the question you asked in the comments, to make the list invariant remove the +
before B
, and also get rid of the type parameter in prepend
. It should just be def pretend(elem: B)
).
How to get around it? The best solution is to simply not use mutable collections. You should not need them in 99% or real life scala code. If you think you need one, there is a 99% you are doing something wrong.