我已在Scala中编写此代码
class MI {
def identity : Int = {
println("came inside MI")
1
}
}
trait DMI extends MI {
override def identity : Int = {
println("came inside DMI")
2 * super.identity
}
}
trait TMI extends MI {
override def identity : Int = {
println("came inside TMI")
3 * super.identity
}
}
class Foo extends TMI with DMI {
override def identity : Int = super[DMI].identity
}
val f = new Foo
f.identity
代码的输出是
came inside DMI
came inside TMI
came inside MI
res5: Int = 6
任何人都可以解释为什么电话会进入TMI?据我说,答案应该是2.
答案 0 :(得分:2)
您正在使用可堆叠行为。当Scala遇到new
时,它会使类线性化。此线性化决定在遇到super
时将调用链中的哪个方法。对于您的示例,Foo
的线性化将类似于:
Foo -> DMI -> TMI -> MI -> AnyRef -> Any
因此,如果在任何方法中遇到super
,则将从右向左选择实现。在这种情况下,由于在super[DMI].identity
的{{1}}方法中使用了identity
:
Foo
执行identity
(因为您已明确使用DMI
不会使用线性化),它再次具有super[DMI]
和
按线性化super.identity
执行identity
,TMI
再次super.identity
并按照线性化identity
MI
这就是为什么你得到6
作为最终输出的原因。
注意如果您从super[TMI].identity
内部调用Foo
,结果将是3
。
有关线性化的更多详细信息,请参阅this链接。
答案 1 :(得分:1)
FOO的结构如下:
TMI与DMI {Foo}
展开所有类型,直至到达任何
(Any with with AnyRef with MI with TMI)with(Any with AnyRef with MI with DMI)with {Foo}
(任何带有带有TMI的MI的AnyRef)和带有{Foo}
的(DMI)AnyRef with MI with TMI with DMI with {Foo}