Scala在飞行中混合特征时表现出不同的行为

Scala在飞行中混合特征时表现出不同的行为,scala,Scala,我认为下面的两个代码快照是等效的,但它们会产生不同的结果。你能解释一下原因吗 1) 添加到类声明中的特性: trait M1 { override def toString() = "m1" } trait M2 { override def toString() = "m2" } class C extends M1 with M2 { override def toString() = { s"C and ${super.toString()}" } } val

我认为下面的两个代码快照是等效的,但它们会产生不同的结果。你能解释一下原因吗

1) 添加到类声明中的特性:

trait M1 {
  override def toString() = "m1"
}
trait M2 {
 override def toString() = "m2"
}
class C extends M1 with M2 {
  override def toString() = {
       s"C and ${super.toString()}"
  }
}

val c = new C
c.toString() //C and m2
2) 动态添加的特征:

class C {
  override def toString() = {
       s"C and ${super.toString()}"
  }
}

val c = new C with M1 with M2
c.toString() //m2

这两种方法并不相同

在应用了mixin之后,版本1将覆盖toString

第二种方法在创建C之后混合,因此M2中的toString将覆盖C中的toString

这里发生了两件有趣的事情,首先是Scala中的混音从右向左扫描。这就是为什么在M1之前调用M2。第二个是新的C和M1以及M2将在幕后创建一个扩展C的合成类。该合成类被增强为包含M2和M1,并且该扩展将覆盖C上的toString方法。其中,声明C扩展M1和M2将直接将行为构建到类C和重写中C上的方法将起作用以获得优先权