我认为以下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
答案 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上的覆盖方法优先使用。