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

标签 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(...) ...

如果注释掉的选项未被取消注释,则上面的示例不会编译,正如我希望的那样,默认情况下会这样做。

是否有更好的方法来实现这一目标?

模组注意:这不是关于在密封类中强制编译错误的问题的重复:我的问题特别是关于全面的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 */ }

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/

相关文章:

ios - 为 iOS 创建/导入 Kotlin 多平台代码

kotlin - 如何模拟调用 kotlin.system.exitProcess

android - 如何从适配器Kotlin增加通知徽章的计数器

ios - JSON 序列化卡住了 UI

kotlin - 如何在 kotlin 中对字符串数组进行排序

docker - 如何设置 micronaut 生成 docker 镜像

kotlin - 当我在 KorGE 中切换到其他场景时出现异常

android - Kapt 注释处理 - 如何显示完整的堆栈跟踪

kotlin - Kotlin用前面两个索引的元素压缩每个元素

kotlin - 检查数组是否包含子字符串?