我有一个返回 Future[Unit]
的方法,所以当我调用 whenReady
这两个选项有效:whenReady(doItAsync())(_ => {})
和whenReady(doItAsync()) { _ => }
但这不是: whenReady(doItAsync())(() => {})
不是类型Unit
的_
,在这种情况下是等价的空参数列表?
尽管类型Unit
类型类似于其他语言的void
,但它并不完全相同。此特定的麻烦来自Java(以及Scala)仿制药的限制:它们是使用类型擦除实现的。特别是这意味着通用方法无法更改参数的数量。现在,当类型参数为 Unit
时会发生什么?我们仍然必须具有相同数量的参数,也不能神奇地将返回类型更改为返回(void
),因为这将是不同的签名。因此,答案是使用一些仅带有假货值的假类型:scala.runtime.BoxedUnit
。因此,Unit
可能代表您不需要但必须存在的实际参数。因此,键入签名() => {}
与该签名不匹配,因为它没有参数。
还请注意,在Java本身中存在相同的问题,因此有一个类似的东西称为java.lang.Void
更新:
使点更清楚地考虑遵循通用和非生成代码:
def foo(f: () => String) = println(f())
def fooGeneric[T](arg: T, f: (T) => String) = println(f(arg))
foo(() => "Non-generic")
fooGeneric[Unit]((), (_) => "generic")
请注意,逻辑上的fooGeneric[Unit]
也与foo
相同,您仍然必须传递第一个参数和传递函数,该函数接受(无用)参数为第二个参数。
在这种情况下,不是_的类型单位和空参数列表吗?
否。_ => {}
定义了具有单个参数的函数(在此上下文中发生的Unit
类型),() => {}
定义一个没有参数的函数。它们的类型是Unit => Unit
和() => Unit
,或没有句法糖Function1[Unit, Unit]
和Function0[Unit]
。这些类型实际上并不相关:它们都不是另一种的亚型。
您可以使用模式匹配:{ case () => ... }
编写单词匿名函数,将Unit
与()
一起使用。但是没有意义。