scala代码:
trait Action{
def doAction
}
trait BeforeAfterOfAction extends Action{
abstract override def doAction: Unit ={
println("before")
super.doAction
println("after")
}
}
class Work extends Action{
override def doAction = println("working....")
}
object Test{
def main(args: Array[String]) {
val work = new Work with BeforeAfterOfAction
work.doAction
}
}
结果是:
before
working....
after
我认为它打印" working....
"只是,但为什么不呢?
您能解释一下流程细节吗?
答案 0 :(得分:2)
当您编写new Work with BeforeAfterOfAction
时,您正在使用可堆叠行为的特征。摘录自Programming in Scala:
Traits允许您修改类的方法,并且它们以某种方式实现 这允许您将这些修改相互堆叠。
您可以详细阅读here。
修改强>
要进一步解释,请键入:
new Work with BeforeAfterOfAction
您实际上正在创建一个等同于以下类定义的mixin:
class MyWork extends Work with BeforeAfterOfAction
现在MyWork
类的线性化将如下:
MyWork -> BeforeAfterOfAction -> Work -> Action -> AnyRef -> Any
当您调用new MyWork().doAction
(其中new MyWork()
等同于new Work with BeforeAfterOfAction
)时,它会doAction
调用BeforeAfterOfAction
,因为MyWork
不会有doAction
方法。
有趣的部分出现在super.doAction
BeforeAfterOfAction
遇到doAction
时。遇到super
时,会选择线性化中第一个右侧的doAction
。在这种情况下,doAction
来自Work
。因此,您会看到如下输出:
before
working....
after
您可以从this链接了解有关线性化的更多信息。
答案 1 :(得分:1)
请考虑以下事项:
val x = new A with B with C
x.meth()
此x
实例混合了特征(或类)A
,B
和C
。调用方法meth()
时,编译器将首先查看C
以查看它是否定义了该方法。如果找不到,则会查看B
,最后查看A
。
在你的例子中:
val work = new Work with BeforeAfterOfAction
work.doAction
...方法doAction
位于BeforeAfterOfAction
,因此是执行的方法。但是在那个方法中是对super.doAction
的调用。什么是BeforeAfterOfAction
的超类?当特质混合时,它就是它之前的任何东西。
因此,编译器首先查看Work
以查看是否在那里定义了doAction
方法。既然如此,那就是被执行的东西。