我在Kotlin中有一个应该返回Unit的函数有麻烦,但是由于使用了另一个返回布尔值的函数,所以存在类型不匹配。
这是一个人为的例子:
fun printAndReturnTrue(bar: Int): Boolean {
println(bar)
return true
}
fun foo(bar: Int): Unit = when(bar) {
0 -> println("0")
else -> printAndReturnTrue(bar)
}
在这里,我实际上并不关心printAndReturnTrue
返回布尔值的事实。我只想让foo执行副作用操作。但是编译器会警告类型不匹配:我的else
应该返回Unit
值。
有没有一种方法可以将值转换为Unit
?
我看到的最简单的解决方案是:
fun foo(bar: Int): Unit = when(bar) {
0 -> println("0")
else -> {
printAndReturnTrue(bar)
Unit
}
}
或:
fun foo(bar: Int): Unit = when(bar) {
0 -> println("0")
else -> eraseReturnValue(printAndReturnTrue(bar))
}
fun eraseReturnValue(value: Any) = Unit
或者我使用完整的函数形式:
fun foo(bar: Int): Unit {
when(bar) {
0 -> println("0")
else -> printAndReturnTrue(bar)
}
}
我确信有一些惯用的方法(或者是最后一个例子?),但是现在我找不到它们。
答案 0 :(得分:7)
不幸的是,没有惯用的方法来做到这一点。一个类似的问题,将(T) -> Boolean
类型的lambda传递给接受(T) -> Unit
lambdas的函数,之前已经出现了,并且在那里需要进行自动转换应该会在将来某个时候出现。
目前,您可以使用when
表达式末尾的扩展功能将其强制转换为Unit
值:
fun Any?.toUnit() = Unit
fun foo(bar: Int): Unit = when(bar) {
0 -> println("0")
else -> printAndReturnTrue(bar)
}.toUnit()
或者,扩展属性,如果你碰巧更喜欢它:
val Any?.unit get() = Unit
fun foo(bar: Int): Unit = when(bar) {
0 -> println("0")
else -> printAndReturnTrue(bar)
}.unit
当然,如果你使用其中任何一个,你可以省略函数的显式Unit
返回类型。
答案 1 :(得分:3)
我认为最后一个是最惯用的。虽然您不需要明确的: Unit
,但如果未指定返回类型,则它是块形式的默认值,如果您尝试返回其他内容,则会收到错误。
但请注意一个细微的细节:当when
用作表达式时,除非编译器能够证明所有情况都得到处理,否则需要else
;在块形式中它用作声明"和未处理的案件被忽略。
答案 2 :(得分:1)
作为另一种选择,你可以创建一个更高阶函数,吞下函数的输出,返回一个值:
fun consume (fn: () -> Any): Unit {
fn()
}
,并提供:
fun foo(bar: Int): Unit = when(bar) {
0 -> println("0")
else -> consume { printAndReturnTrue(bar) }
}
答案 3 :(得分:0)
我认为你应该将函数的返回类型更改为可选,它更清楚,如下所示:
def buttonCollide():
global state
...
答案 4 :(得分:0)
如果我在一行中写,我只会使用分号。
someExpression; Unit
答案 5 :(得分:0)
您也可以做类似的事情
fun foo(bar: Int): Unit = when(bar) {
0 -> println("0")
else -> printAndReturnTrue(bar).let{ Unit }
}