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

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!

被打印。

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

最佳答案

第一条语句:

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!

作为输出。

自定义控制结构

我想您打算使用第二个语句创建 custom control structure (尽管对于编译器,它是一个匿名类)。如果是这种情况,您可以使用以下语法:
val runner = new Runner()
runner.apply {println("procedure!")}
// OR simply
runner {println("procedure!")} // this is possible because apply() is defined for Runner

关于Scala 函数不按名称用大括号(大括号)传递,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36745232/

10-11 22:35
查看更多