堆叠特质中super的含义取决于致电地点? [英] Meaning of super in stacked traits depends on call site?

查看:76
本文介绍了堆叠特质中super的含义取决于致电地点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法用语言对它进行很好的描述,因此,请看下面的示例:

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相同),特征堆栈"非常明显. Twofoo调用其上级(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. Foobar调用其上级(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆