Confusion about self-type and override: Why can I successfully override a method without inheriting a base class or trait?

I did some experiments:

trait IA {
  def play(): Unit = {
    println("IA play")
  }
}

class B {
  this: IA => 
  override def play() = {
    println("B play")
  }
}

The following two pieces of code will fail to compile:

class MyClass extends IA with B // failed
class MyClass extends B with IA // failed

Following my judgement above:

The another difference between classes and traits is that whereas in classes, override are statically bound, in traits, they are dynamically bound.

B is a class, the override of play should be statically bound, so it must override the play in IA, but we can not syntactically write:

class MyClass extends IA with B

becasue a class cannot appear on the right side of the with.

We also cannot write:

class MyClass extends B with IA

because of linearization, IA should override B, not B override IA.

To fix this, we must make B trait instead of class and exchange order in MyClass

trait IA {
  def play(): Unit = {
    println("IA play")
  }
}

trait B {
  this: IA => 
  override def play() = {
    println("B play")
  }
}

class MyClass3 extends IA with B // success
1 Like