在 Scala 中使用按名称调用函数时,我遇到了一些意外行为。有人能解释一下这里的区别吗?
class Button( act: => Unit) {def fire = act}
def foo() {println("foo got called")}
val x= new Button(foo)
x.fire
val y= new Button(foo _)
y.fire
Run Code Online (Sandbox Code Playgroud)
x.fire 导致 foo 被调用。y.fire 没有。为什么?什么函数被传递给 y?谢谢!
您可能应该稍微不同地定义您的类。
class Button( act: () => Unit) {def fire = act()}
Run Code Online (Sandbox Code Playgroud)
请注意,您现在采用的是 aFunction0[Unit]而不是按名称调用Unit值。这个新定义具有更好的类型安全性,因为它需要一个函数,而您的定义将接受任何值,并且不会执行任何操作,除非需要评估传入的值有副作用。我们现在还称传入的函数是因为它的副作用,而不是只是归还它。
问题Unit是,当需要一个单位时,可以提供任何值,这些值将被自动丢弃Unit。例如,您的代码new Button(5)是有效的,代码也是有效的val x: Unit = 5。
第一个代码“有效”的原因class Button( act: => Unit) {def fire = act}是您调用方法 foo,并将结果传递到Button构造函数中。由于它是一个按名称参数,因此foo在使用之前实际上不会运行。然后,当您使用传递到类中的 Unit 值时,需要对表达式进行求值,因此foo很有趣。
但是,第二个示例有所不同,添加下划线 ( foo _) 现在意味着您将方法本身作为函数传递,而不是像第一个示例中那样调用方法并传递结果。即使现在的类型不是,将函数传递给构造函数也是完全可以的,Unit因为如前所述,任何值都可以被丢弃并替换为Unit。当您计算 Unit 值时,这次没有副作用,因为您没有运行获取单位的方法,只是创建一个函数,该函数在不运行的情况下被丢弃。 def fire = act
当您将类型更改为函数时。
class Button( act: () => Unit) {def fire = act()}
Run Code Online (Sandbox Code Playgroud)
现在只有 a() => Unit是有效参数,而不是任何参数,并且 fire 方法运行该函数。