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 选择 && 作为守卫的连接符,那么在编写多条件时,可读性就会大大降低,也不利于理解。

相关推荐
alexhilton2 分钟前
为什么你的App总是忘记所有事情
android·kotlin·android jetpack
AirDroid_cn3 小时前
OPPO手机怎样被其他手机远程控制?两台OPPO手机如何相互远程控制?
android·windows·ios·智能手机·iphone·远程工作·远程控制
尊治3 小时前
手机电工仿真软件更新了
android
xiangzhihong86 小时前
使用Universal Links与Android App Links实现网页无缝跳转至应用
android·ios
车载应用猿7 小时前
基于Android14的CarService 启动流程分析
android
没有了遇见8 小时前
Android 渐变色实现总结
android
雨白10 小时前
Jetpack系列(四):精通WorkManager,让后台任务不再失控
android·android jetpack
mmoyula12 小时前
【RK3568 驱动开发:实现一个最基础的网络设备】
android·linux·驱动开发
sam.li13 小时前
WebView安全实现(一)
android·安全·webview
移动开发者1号14 小时前
Kotlin协程超时控制:深入理解withTimeout与withTimeoutOrNull
android·kotlin