Kotlin takeIf 和 takeUnless

       除了作用域函数之外,标准库还包含函数 takeIf 和 takeUnless。这些函数允许你在调用链中对对象状态进行检查。

       这两个函数的作用是对象过滤器,如果该对象与条件匹配,takeIf将返回该对象。否则返回null。takeIf是单个对象的过滤函数。反过来,如果takeUnless与条件不匹配,则返回该对象;如果匹配,则返回null。该对象可以作为lambda参数(it)使用,过滤条件位于函数的 {} 中。

1
2
3
4
5
6
7
8
9
import kotlin.random.*

fun main() {
val number = Random.nextInt(100)

val evenOrNull = number.takeIf { it % 2 == 0 }
val oddOrNull = number.takeUnless { it % 2 == 0 }
println("偶数: $evenOrNull, 奇数: $oddOrNull")
}

       在 takeIf 和 takeUnless 之后链接其它函数时,不要忘记执行空检查或安全调用(?.),因为它们的返回值是可空的。

1
2
3
4
5
6
fun main() {
val str = "Hello"
val caps = str.takeIf { it.isNotEmpty() }?.toUpperCase()
//val caps = str.takeIf { it.isNotEmpty() }.toUpperCase() //编译出错
println(caps)
}

       takeIf 和 takeUnless 与作用域函数一起使用时特别有用。一个很好的例子是使用 let 来链接它们,以便在与给定条件匹配的对象上运行代码块。为此,请先调用 takeIf 对象,然后使用安全调用(?.let)进行调用。对于与条件不匹配的对象,takeIf 将返回 null 并且 let 不会被调用。

1
2
3
4
5
6
7
8
9
10
11
fun main() {
fun displaySubstringPosition(input: String, sub: String) {
input.indexOf(sub).takeIf { it >= 0 }?.let {
println("The substring $sub is found in $input.")
println("Its start position is $it.")
}
}

displaySubstringPosition("010000011", "11")
displaySubstringPosition("010000011", "12")
}

       下面是没有使用标准库函数实现相同的功能:

1
2
3
4
5
6
7
8
9
10
11
12
fun main() {
fun displaySubstringPosition(input: String, sub: String) {
val index = input.indexOf(sub)
if (index >= 0) {
println("The substring $sub is found in $input.")
println("Its start position is $index.")
}
}

displaySubstringPosition("010000011", "11")
displaySubstringPosition("010000011", "12")
}

       举一个 takeUnless 的例子,如果路径下的某个文件是可见的,则读取其中的内容:

1
2
3
4
val result = File(pathName)
.takeUnless { it.isHidden }
?.readText()
println(result)

参考资料:
Kotlin
SkyRiN Kotlin | 作用域函数
动脑学院 《Android高级课程》VIP试听课

Fork me on GitHub