-2

I have class

class GenericClass[+T] (var x: T) {}

When I try to compile it I get:

Error:(6, 33) covariant type T occurs in contravariant position in type T of value x_=
  class GenericCellImm[+T] (var x: T) {

How to fix it? What is the problem reason?

jwvh
  • 50,871
  • 7
  • 38
  • 64
tugot17
  • 11
  • 2
  • 2
    Quite probably [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) (BTW using var is anyway discouraged) – cchantep Jan 12 '18 at 22:13
  • The compiler knows where a covariant type would not be type-safe and does not allow that. The passed parameter can be a `var` or the type can be covariant, but you can't have both. – jwvh Jan 12 '18 at 22:45
  • 1
    The answer to [this question](https://stackoverflow.com/questions/28570877/java-covariant-array-bad) demonstrates the dangers of mixing covariant types with mutable variables. – jwvh Jan 12 '18 at 23:08

1 Answers1

1

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.

SergGr
  • 23,570
  • 2
  • 30
  • 51