在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
x.fire导致foo被调用。
y.fire没有。
为什么?
什么函数传递给y?
谢谢!
最佳答案
您可能应该对类进行一些不同的定义。
class Button( act: () => Unit) {def fire = act()}
请注意,您现在正在使用
Function0[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()}
现在只有
() => Unit
是有效的参数,而不是任何参数,并且fire方法运行该函数。