Clarification on why I cannot override a method using a generic class parameter by a subtype of it

Viewed 95

Given the following situation (scastie)

trait Element
class Earth extends Element

trait Container[T]
class ContainerEarth extends Container[Earth]

trait Dummy[E <: Element] {

  def dummy(container: Container[E]): Any
}

class EarthDummy extends Dummy[Earth] {

  def dummy(container: ContainerEarth): Any = ??? // could not override
  override def dummy(container: Container[Earth]): Any = ???
}

It's still not clear in my head, why ContaineEarth could not override.

I have a solution to get around the business problem, but I need to understand why does the compiler refuse the substitution.

trait Dummy[E <: Element, C <: Container[E]] {

  def dummy(container: C): Any
}

I've been given that variance is in the game, and prevent it.

But for me, variance is about Container[Dirt] being a subtype of Container[Earth] if Dirt extends Earth when Container generic parameter is covariant.

So I'm open to all of your clarifications.

1 Answers

Trait Dummy[E <: Element] describes a contract. A class implementing this trait must have method dummy accepting arbitrary container: Container[E].

DirtDummy is-a Dummy[Earth]. So its method dummy must accept arbitrary container: Container[Earth]. If it accepted only ContainerEarth it would not be able to handle container that has type Container[Earth] but doesn't have type ContainerEarth:

class AnotherContainerEarth extends Container[Earth]

new DirtDummy().dummy(new AnotherContainerEarth)

So this would be a violation of the contract.

When you define def dummy(container: ContainerEarth): Any this is not overriding but overloading.

Related