堆叠特质中super的含义取决于致电地点? [英] Meaning of super in stacked traits depends on call site?
问题描述
我无法用语言对它进行很好的描述,因此,请看下面的示例:
I can't come up with a very good description of this in words, so, please take a look at this example:
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
此打印:Two <: One <: Base
,这是我所期望的.
现在,我尝试添加另一个级别,以便覆盖特征不必显式调用super
.像这样:
This prints: Two <: One <: Base
, which is what I expect.
Now, I am trying to add another level, so that overriding traits would not have to call super
explicitly. Like this:
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
在这里,最后一行打印出Two <: Base
Here, the last line prints out Two <: Base
因此,在第一个示例中,super
的意思是One
,而在最后一个示例中,它跳过了One
并直接进入了Base
.
So, it looks like in the first example super
means One
, while in the last one it skips One
and goes directly to Base
.
为什么会这样?行为不应该一样吗?
Why is this happening? Shouldn't behavior be the same?
推荐答案
在第一种情况下,new Base with One with Two {} foo
(与new One with Two {} foo
相同),特征堆栈"非常明显. Two
的foo
调用其上级(One
)的foo
,该c10调用其上级(Base
)的foo
.
In the 1st case, new Base with One with Two {} foo
(which is the same as new One with Two {} foo
), the "trait stack" is pretty obvious. The Two
has a foo
which calls the foo
of its super (One
) which calls the foo
of its super (Base
).
在第二种情况下,new Foo with One with Two {} bar
(与new One with Two {} bar
相同),特征堆栈"是Base-> Foo-> One-> Two.您调用bar
,但是Two
没有bar
,而One
没有bar
. Foo
的bar
调用其上级(Base
)的foo
.
In the 2nd case, new Foo with One with Two {} bar
(which is the same as new One with Two {} bar
), the "trait stack" is Base->Foo->One->Two. You call bar
but Two
has no bar
and One
has no bar
. Foo
has a bar
that calls the foo
of its super (Base
).
更新
按照@Dima的建议考虑此mod.
Consider this mod as @Dima has proposed.
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
Yes, this gives the same output as before: res0: String = Two <: Base
现在Two
调用其上级(One
)的bar
,它调用其上级(Foo
)的bar
,后者又调用其上级的foo
(不是bar
).
Now Two
calls the bar
of its super(One
) which calls the bar
of its super (Foo
) which calls the foo
(not bar
) of its super.
所有这些bar
活动都与foo
定义分开. Two
永远不会调用其上级的foo
,因此永远不会使用One.foo
,并且不能将其作为输出的一部分.
All this bar
activity is separate from the foo
definitions. Two
never invokes the foo
of its super so the One.foo
is never used and cannot be a part of the output.
一种不同的方法
请考虑以下内容.
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
现在尝试以多种不同的方式实例化它.
Now try instantiating this in multiple different ways.
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
之前的特征(或B
,如果在R
之前未指定任何内容).
In each case r.id
will be the last trait in the chain and r.mySup
will be the trait that comes before the R
(or B
if nothing is specified before the R
).
这篇关于堆叠特质中super的含义取决于致电地点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!