
Kotlin 一直在改进。
Kotlin 2.5.0-Beta2 中提供了三个实验性的标准库函数(已在 2.5.0-Beta1 的发布记录中列出):
onTrue()onFalse()ifOrNull()
它们可以减少重复的 if-else 表达式,让一些常见的 Kotlin 写法更容易读懂。
我发现现代语言在语法糖上有个小趋势,就是支持更多链式调用的写法。
下面用 Android 中的常见场景说明它们的用法。
1. onTrue() 和 onFalse()
它们做什么
假设我们需要根据一个布尔结果执行操作。比如:
- 登录成功,记录成功日志。
- 登录失败,记录错误日志。
- 支付成功,触发埋点事件。
通常,我们会写一个 if-else 代码块来处理。
以前:使用 if-else
有一个 Android 登录页面。验证用户凭据后,我们希望记录认证成功还是失败。
kotlin
fun authenticate(user: User, token: String): Boolean {
val isAuthenticated = verifyToken(user.email, token)
if (isAuthenticated) {
logSuccess("Login successful")
} else {
logFailure("Login failed")
}
return isAuthenticated
}
这段代码没有问题,也是我们已经很熟悉的写法。
现在:使用 onTrue() 和 onFalse()
kotlin
@OptIn(ExperimentalStdlibApi::class)
fun authenticate(user: User, token: String): Boolean =
verifyToken(user.email, token)
.onTrue {
logSuccess("Login successful")
}
.onFalse {
logFailure("Login failed")
}
是不是有点像 Result 的处理方法?
怎么理解
onTrue():
- 只有布尔值为
true时,才执行 lambda。 - 值为
false时,不执行任何操作。 - 返回原来的布尔值。
onFalse():
- 只有布尔值为
false时,才执行 lambda。 - 值为
true时,不执行任何操作。 - 返回原来的布尔值。
例如:
kotlin
@OptIn(ExperimentalStdlibApi::class)
val result = true
.onTrue { println("Success") }
.onFalse { println("Failure") }
println(result) // true
其实很简单!
什么时候适合用?这取决于你的喜好和需求,不过可以参考下面几个场景:
- 记录成功或失败日志。
- 触发埋点事件。
- 显示轻量提示。
- 根据结果执行回调。
如果只是根据 Boolean 值执行操作,并保留原来的布尔结果,就可以考虑这两个函数。
这两个函数适合处理副作用,不会把布尔值转换成其他值。
2. ifOrNull()
它做什么
有时,我们只想在条件成立时返回一个值,条件不成立时返回 null。
比如用户资料页:用户可能填写了电话号码,也可能没有。只有存在联系信息时,我们才希望提供电话号码。
以前:使用 if-else
kotlin
val phoneNumber = if (user.hasContactInfo) {
user.phoneNumber
} else {
null
}
在 Kotlin 2.5.0-Beta2 中,可以用一种更短的写法。
现在:使用 ifOrNull()
kotlin
@OptIn(ExperimentalStdlibApi::class)
val phoneNumber = ifOrNull(user.hasContactInfo) {
user.phoneNumber
}
怎么理解
可以把 ifOrNull() 理解为一个根据条件提供值的函数:
- 条件为
true时,执行 lambda 并返回它的结果。 - 条件为
false时,返回null。 - 条件为
false时,不会执行 lambda。
实际场景:映射 API 响应
假设在 Android 开发中,一个 API 返回用户资料。有些用户有联系信息,有些没有。
kotlin
data class User(
val name: String,
val hasContactInfo: Boolean,
val phoneNumber: String?
)
我们希望只在存在联系信息时,才为资料页准备要显示的电话号码。
kotlin
@OptIn(ExperimentalStdlibApi::class)
fun getDisplayPhoneNumber(user: User): String? {
return ifOrNull(user.hasContactInfo) {
user.phoneNumber ?: "No phone number"
}
}
这样:
hasContactInfo为true时,执行 lambda,返回电话号码或兜底文案。hasContactInfo为false时,结果为null。
映射 API 响应、准备可选的 UI 数据、创建 DTO 时,都可以用到这种写法。
3. 能力速查
| 函数 | 作用 | 返回值 |
|---|---|---|
onTrue() |
值为 true 时执行操作 |
原来的布尔值 |
onFalse() |
值为 false 时执行操作 |
原来的布尔值 |
ifOrNull() |
条件为 true 时执行代码块 |
代码块的结果或 null |
4. 仍处于实验阶段
在 Kotlin 2.5.0-Beta2 中,这些函数仍是实验性 API。使用时需要显式选择启用:
kotlin
@OptIn(ExperimentalStdlibApi::class)
也可以在项目中通过编译器选项 -opt-in=kotlin.ExperimentalStdlibApi 统一启用。
本文以 Beta2 版本为例。在生产代码中采用这些 API 前,请先查看最新的 Kotlin 文档,确认它们的状态和用法。
5. 一点想法
这三个函数改动不大,但让常见的 Kotlin 写法更容易表达意图。遇到重复的条件代码块时,可以直接写出要做的事:
- 成功时执行操作,用
onTrue()。 - 失败时执行操作,用
onFalse()。 - 根据条件返回值,用
ifOrNull()。
当然,代码行数并不是唯一的目标,更重要的是让代码容易理解和维护。
还有一点,正如我开头提到的那样,现代语言越来越支持链式调用。写完一个函数调用后,我可以自然地继续使用 . 调用下一个函数去处理结果。在这类场景下,相比使用 if-else,这样的写法确实更简洁,写起来也更流畅。
可能这也是为什么曾经 RxJava 如此流行的原因之一吧。