Scala在动态混合时的不同行为

时间:2015-10-15 16:23:33

标签: scala

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

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

1 个答案:

答案 0 :(得分:3)

这两种方法并不相同。

版本1在应用mixins后覆盖toString。

第二种方法在创建C之后混入,因此M2中的toString会覆盖C上的toString。

这里发生了两件有趣的事情,首先在Scala中的mixins从右到左扫描。这就是M1在M1之前调用的原因。第二个是带有M1和M2的新C将在幕后创建一个合成类,扩展C。合成类被增强到包括M2和M1,这个扩展将覆盖C上的toString方法。其中声明C为扩展M1和M2直接将行为直接构建到类C中,并且C上的覆盖方法优先使用。