我无法用语言对此进行非常好的描述,所以,请看一下这个例子:
trait Base { def foo = "Base" }
trait One extends Base { override def foo = "One <: " + super.foo }
trait Two extends Base { override def foo = "Two <: " + super.foo }
new Base with One with Two {} foo
这打印:两个<:One< ;: Base,这是我所期待的.
现在,我正在尝试添加另一个级别,以便覆盖的特征不必显式调用super.像这样:
trait Base { def foo = "Base" }
trait Foo extends Base { def bar = foo + " <: " + super.foo }
trait One extends Foo { override def foo = "One" }
trait Two extends Foo { override def foo = "Two" }
new Foo with One with Two {} bar
这里,最后一行打印出两个< ;: Base
因此,在第一个例子中看起来像super表示One,而在最后一个示例中它跳过One并直接转到Base.
为什么会这样?不应该是一样的行为吗?
最佳答案 在第一种情况下,新的Base with One with Two {} foo(与新的One with two {} foo相同),“trait stack”非常明显. Two有一个foo,它调用超级(One)的foo,它调用超级(Base)的foo.
在第二种情况下,新的Foo与One with Two {} bar(与具有Two {} bar的新One相同),“trait stack”是Base-> Foo-> One-> Two.你打电话给酒吧,但是两个没有酒吧,一个没有酒吧. Foo有一个叫它super(Base)的foo的吧.
UPDATE
考虑@Dima提出的这个mod.
trait Base { def foo = "Base" }
trait Foo extends Base { def bar = foo + " <: " + super.foo }
trait One extends Foo { override def bar = super.bar
override def foo = "One" }
trait Two extends Foo { override def bar = super.bar
override def foo = "Two" }
new One with Two {} bar // no Base or Foo needed
是的,这给出了与之前相同的输出:res0:String = Two<:Base 现在两个调用超级(One)的栏,它调用超级(Foo)的栏,调用其超级的foo(不是栏). 所有这些bar活动都与foo定义分开.两个从不调用它的超级foo,所以One.foo从未使用过,也不能成为输出的一部分. 一种不同的方法 考虑以下.
trait B { def id = "B" } // B for Base
trait V extends B { override def id = "V" }
trait W extends B { override def id = "W" }
trait X extends B { override def id = "X" }
trait Y extends B { override def id = "Y" }
trait Z extends B { override def id = "Z" }
trait R extends B { override def id = "R"; def mySup = super.id } // Required
现在尝试以多种不同的方式实例化它.
val r = new V with Y with W with R with X {} // B not needed
// or
val r = new W with R with Z with X with V {}
// or
val r = new R with Y with V with B with W {}
// or
val r = new Z with Y with X with W with R {}
// etc.
在每种情况下,r.id将是链中的最后一个特征,r.mySup将是R之前的特征(如果在R之前没有指定,则为B).