如何理解这个scala代码?

时间:2016-05-06 07:21:53

标签: scala traits

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

您能解释一下流程细节吗?

2 个答案:

答案 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实例混合了特征(或类)ABC。调用方法meth()时,编译器将首先查看C以查看它是否定义了该方法。如果找不到,则会查看B,最后查看A

在你的例子中:

val work = new Work with BeforeAfterOfAction
work.doAction

...方法doAction位于BeforeAfterOfAction,因此是执行的方法。但是在那个方法中是对super.doAction的调用。什么是BeforeAfterOfAction的超类?当特质混合时,它就是它之前的任何东西。

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