Kotlin 守卫——更加强大的 when 表达式

2.1.0 版本开始,你可以在带有主题的 when 表达式或语句(when (subject))中使用守护条件。

守护条件允许你为 when 表达式的各个分支设置多个条件,这使得复杂的控制流更加清晰简洁,同时也简化了代码结构。

因为该特性在 2.1.0 版本还是 preview 阶段,所以需要启用此特性:

Kotlin 复制代码
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xwhen-guards")
    }
}

在完成如上的设置之后,我们便可以使用守卫特性了。

Kotlin 复制代码
sealed interface Animal {
    data class Cat(val mouseHunter: Boolean) : Animal
    data class Dog(val breed: String) : Animal
}

fun feedAnimal(animal: Animal) {
    when (animal) {
        // 仅带有主要条件的分支
        is Animal.Dog -> { println("I eat ${animal.breed}") }
        // 同时带有主要条件和守护条件的分支
        is Animal.Cat if !animal.mouseHunter -> { println("I am a pet eat cat food") }
        // 如果上述条件均不匹配
        is Animal.Cat -> println("I eat mouse")
    }
}

fun main() {
    feedAnimal(Animal.Cat(true))
    feedAnimal(Animal.Cat(false))
    feedAnimal(Animal.Dog("Meat"))
}

// Output
// I eat mouse
// I am a pet eat cat food
// I eat Meat

在单个 when 表达式中,你可以组合带有和不带有守护条件的分支。只有当主要条件和守卫条件都为真时,带有守护条件的分支中的代码才会运行。如果主要条件不匹配,则不会计算守护条件。此外,守护条件支持 else if

上述代码中,最后一个语句是 is Animal.Cat,此时你可以不用写 else 语句,因为编译器会检查你的 when 表达式是否穷尽。

为什么不用 && ?

有的编程语言使用了 && 作为守卫表达式的连接符,Kotlin 此处使用了 if,为什么呢?

Kotlin 复制代码
var a = 10
when {
    a < 100 && a > 0 -> {
        println("under 100")
    }
    else -> {
        println("others")
    }
}

Kotlin 在无主题的 when 表达式中,判断条件就是使用 && 作为连接符的,同时,在守卫条件中,if 表达式如果有多个条件,也需要使用 && 或者 ||

Kotlin 复制代码
var a = 10
when(a) {
    is Long if (a < 100 && a > 0) -> {
        println("under 100")
    }
    else -> {
        println("others")
    }
}

如果 Kotlin 选择 && 作为守卫的连接符,那么在编写多条件时,可读性就会大大降低,也不利于理解。

相关推荐
硬件学长森哥11 小时前
Android影像基础--cameraAPI2核心流程
android·计算机视觉
前行的小黑炭15 小时前
Android 协程的使用:结合一个环境噪音检查功能的例子来玩玩
android·java·kotlin
阿华的代码王国16 小时前
【Android】内外部存储的读写
android·内外存储的读写
inmK119 小时前
蓝奏云官方版不好用?蓝云最后一版实测:轻量化 + 不限速(避更新坑) 蓝云、蓝奏云第三方安卓版、蓝云最后一版、蓝奏云无广告管理工具、安卓网盘轻量化 APP
android·工具·网盘工具
giaoho19 小时前
Android 热点开发的相关api总结
android
咖啡の猫21 小时前
Android开发-常用布局
android·gitee
程序员老刘21 小时前
Google突然“变脸“,2026年要给全球开发者上“紧箍咒“?
android·flutter·客户端
Tans521 小时前
Androidx Lifecycle 源码阅读笔记
android·android jetpack·源码阅读
雨白1 天前
实现双向滑动的 ScalableImageView(下)
android
峥嵘life1 天前
Android Studio新版本编译release版本apk实现
android·ide·android studio