Search code examples
scalavariantcovariant

Why not set covariant as default when define subtype in Scala?


It means define trait Option[T] is same as trait Option[+T].

It's easy to consider val humanOpt: Option[Human] can point to a Option[Student] instance just like val humanOpt: Human can point to a Student instance.

Maybe it seems some strange but why I consider this?

Java variable default as polymorphism which compare with c++ that it should use virtual keyword.I think its a important point to simplify OO in Java.

Scala use high order type in many use case that is more frequently compare to Java, such as Option, Try or define a Cache[T] by ourselves.

Besides, it still comply with Liskov Substitution principle.

I just want to know why not simplify covariant as default behavior?


Solution

  • or define a Cache[T] by ourselves

    If your Cache has a put(T) method, it can't be covariant, exactly because of the Liskov substitution principle.

    val humanCache: Cache[Human] = new Cache[Student] // legal if cache is covariant
    humanCache.put(new Professor) // oops, we put a Professor into a Cache[Student]
    

    So making all types covariant by default simply won't work.

    You could use variance inference instead: if type can be covariant make it covariant, if it can be contravariant make if contravariant, if neither make it invariant. But then just adding a method can change the variance and break a lot of code using your type. By making all variance explicit you are forced to notice when you do that.