如何理解这段scala代码?

How to understand this scala code?

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....”,但为什么不呢?

你能解释一下过程细节吗?

当您编写 new Work with BeforeAfterOfAction 时,您正在使用特征的 可堆叠行为 。摘自Programming in Scala

Traits let you modify the methods of a class, and they do so in a way that allows you to stack those modifications with each other.

你可以详细阅读here

编辑

为了进一步解释,当您键入:

new Work with BeforeAfterOfAction

您实际上是在创建一个等同于以下 class 定义的混入:

class MyWork extends Work with BeforeAfterOfAction

现在 MyWork class 的线性化如下:

MyWork -> BeforeAfterOfAction -> Work -> Action -> AnyRef -> Any

当您调用 new MyWork().doAction(其中 new MyWork() 等同于 new Work with BeforeAfterOfAction)时,它会从 BeforeAfterOfAction 调用 doAction,因为 MyWork没有 doAction 方法。

有趣的部分出现在 BeforeAfterOfActiondoAction 中遇到 super.doAction。当遇到 super 时,从线性化的第一个右边开始选择 doAction。在这种情况下是 Work 中的 doAction。因此,您会看到如下输出:

before
working....
after

您可以从 this link.

阅读更多关于线性化的信息

考虑以下因素:

val x = new A with B with C
x.meth()

x 的这个实例是特征(或 classes)ABC 的混合。当调用方法 meth() 时,编译器将首先查看 C 以查看它是否定义了该方法。如果未找到,它将在 B 中查找,最后在 A.

中查找

在你的例子中:

val work = new Work with BeforeAfterOfAction
work.doAction

...方法 doActionBeforeAfterOfAction 中找到,因此这就是被执行的方法。但在该方法中是对 super.doAction 的调用。 BeforeAfterOfAction的超class是什么?当特征混合时,它是它之前的任何东西。

因此,编译器首先查看Work,看看是否在那里定义了doAction方法。既然如此,那就是被执行的。