令人惊讶的是,我发现,如果结果未分配,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(...) ...
如果注释掉的选项未被取消注释,则上面的示例不会编译,正如我希望的那样,默认情况下会这样做。
是否有更好的方法来实现这一目标?
模组注意:这不是关于在密封类中强制编译错误的问题的重复:我的问题特别是关于全面的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
的右大括号之后添加一些函数调用。它可能是一个无意义的调用,例如 let
、apply
或 run
,其 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 */ }
如article中所示由 @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
关于kotlin - 如何强制 Kotlin "when"涵盖所有可能的选项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64133658/