如何强制 Kotlin "何时"涵盖所有可能的选项?



我发现,令人惊讶的是,如果未分配结果,Kotlin的when表达式不会强制处理所有可能的选项。

此示例编译:

import Options.*
fun main() {
print(Options.Great)
print(Options.Medium)
print(Options.TooLittle("needs more"))
}
fun print(opts: Options) {
when (opts) {
//        Great -> println("It's great")
Medium -> println("It's so so...")
is TooLittle -> println("It's not enough because: ${opts.reason}")
}
}
sealed class Options {
object Great: Options()
object Medium: Options()
data class TooLittle(val reason: String): Options()    
}

打印:

It's so so...
It's not enough because: needs more

注意它少了一个箱子。

我一直在将when表达式的结果分配给一个未使用的变量,只是为了增强可理解性。。。

@Suppress("UNUSED_VARIABLE") val ignore = when(...) ...

如果注释掉的选项没有被取消注释,上面的例子就不会编译,就像我希望默认情况下那样。

有更好的方法来实现这一点吗?

mods注意:这不是关于在密封类中强制编译错误的问题的重复:我的问题特别是关于全面的when语句,它涉及密封类,就像在我的例子中一样,但也可以包括其他东西,比如枚举和具有有限大小写的类型,比如Boolean

关键是when被强制覆盖所有可能的选项,当且仅当它是一个表达式而不是一个语句,也就是说,如果它处于以某种方式使用其结果值的位置。

一种解决方案是将结果分配给一个变量,但这会导致一个未使用的变量警告:

val coverAllOptions = when (opts) {
Great -> println("It's great")
Medium -> println("It's so so...")
is TooLittle -> println("It's not enough because: ${opts.reason}")
}

另一个可行但也会导致IDE警告的选项是在when语句之后添加强制转换as Unit

我个人更喜欢的另一个解决方案是在when的右大括号后面添加一些函数调用。它可能是一个无意义的调用,例如letapplyrun,其中lambda为空,并且只包含一个记录目的的注释:

when (opts) {
Great -> println("It's great")
Medium -> println("It's so so...")
is TooLittle -> println("It's not enough because: ${opts.reason}")
}.run { /* cover all options */ }

正如@al3c在文章中所建议的那样,如果您经常需要,您可以创建一个扩展函数或一个扩展属性,它什么都不做,只用于将其附加到when表达式:

val Any?.exhaustive get() = Unit
when (opts) {
Great -> println("It's great")
Medium -> println("It's so so...")
is TooLittle -> println("It's not enough because: ${opts.reason}")
}.exhaustive

相关内容

最新更新