4

我想通过名称传递一个函数,在它执行之前做一些事情。考虑以下示例:

class Runner {
  def apply(procedure: => Unit) = {
    println("running procedure")
    procedure
  }
}

new Runner()(println("procedure!")) // #1
new Runner(){println("procedure!")} // #2

调用 #1 和 #2 之间的唯一区别在于花括号。虽然第一个呼叫输出

running procedure
procedure!

正如预期的那样,仅在第二次通话中

procedure!

被打印。

似乎使用大括号时,过程不是按名称传递而是执行。为什么在这个例子中大括号和圆括号不能互换?

4

1 回答 1

11

第一个声明:

new Runner()(println("procedure!")) // #1

在第一种情况下,当使用括号时,apply()方法被调用并println("procedure!")作为参数传递。所以第一条语句等价于:

new Runner().apply(println("procedure!"))

因此输出为:

running procedure
procedure!

第二个声明:

new Runner(){println("procedure!")} // #2

而在第二种情况下,您正在通过扩展创建一个匿名类Runner。所以在第二种情况下,语句println("procedure!")作为构造函数的一部分执行,但apply()没有被调用,因此你只看到

procedure!

作为输出。

自定义控制结构

我想您打算通过使用第二条语句来创建自定义控制结构(尽管对于编译器,它是一个匿名类)。如果是这种情况,您可以使用以下语法:

val runner = new Runner()
runner.apply {println("procedure!")}
// OR simply 
runner {println("procedure!")} // this is possible because apply() is defined for Runner
于 2016-04-20T13:32:01.543 回答