Covariant generic type means that if you have classes Base
and Child
that extends Base
, then in every context where GenericClass[Base]
is a correct type using an object of type GenericClass[Child]
will also be correct. As a rough approximation it means that if your GenericClass[T]
provides read-only API, you may make +T
covariant because it is always safe to return Child
instead of Base
. However this is not true if you have some writeable API in your GenericClass[T]
. Consider following code:
def writeDefault(gc: GenericClass[Base]):Unit = {
gc.x = new Base()
}
This code is safe if gc
is really of type GenericClass[Base]
but if you let GenericClass[Child]
there, you'll write a value of type Base
to a field that is typed with Child
and this breaks expected type safety. Consider
class Base(){}
class Child(childField:Int) extends Base {}
def bad():Unit = {
val gc = new GenericClass[new Child(1)]
writeDefault(gc)
println(gc.childField) // Oops! there is no childField in Base
}
And this is exactly why the compiler doesn't allow your code with covariance.
If you want get some real suggestion on how to fix it, you should describe the higher-level problem you are trying to solve. Without such a description it is really hard to guess whether just using val
instead of var
is what you need or whether you just need to remove covariance altogether or if you need a more complicated code.