除了作用域函數(shù)外,標準庫還包含函數(shù) takeIf
及 takeUnless
看看 takeIf 和 takeUnless 的實現(xiàn):
// takeIf
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
contract {
callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
}
return if (predicate(this)) this else null
}
// takeUnless
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
contract {
callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
}
return if (!predicate(this)) this else null
}
takeIf : 接收一個判斷條件表達式,如果判斷表達式為 true 則返回對象本身匿乃,false返回 null乌庶。
takeUnless: 與 takeIf 相反, 如果判斷表達式為 true 則返回 null并齐,false 返回對象本身舷蒲。
該對象可以作為 lambda 參數(shù) (it) 使用,過濾條件位于函數(shù)的 {} 中
fun main() {
val number = Random.nextInt(100)
val evenOrNull = number.takeIf { it % 2 == 0 }
val oddOrNull = number.takeUnless { it % 2 == 0 }
println("偶數(shù): $evenOrNull, 奇數(shù): $oddOrNull")
}
控制臺輸出:
偶數(shù): 80, 奇數(shù): null
當在 takeIf
及 takeUnless
之后鏈式調(diào)用其他函數(shù)混驰,不要忘記執(zhí)行空檢查或安全調(diào)用(?.
),因為他們的返回值是可為空的皂贩。
fun main() {
val str = "Hello"
val caps = str.takeIf { it.isNotEmpty() }?.toUpperCase()
//val caps = str.takeIf { it.isNotEmpty() }.toUpperCase() // 編譯錯誤
println(caps)
}
控制臺輸出:
HELLO
takeIf
及 takeUnless
與作用域函數(shù)一起特別有用栖榨。 一個很好的例子是用 let
鏈接它們,以便在與給定謂詞匹配的對象上運行代碼塊明刷。 為此婴栽,請在對象上調(diào)用 takeIf
,然后通過安全調(diào)用(?.
)調(diào)用 let
辈末。對于與謂詞不匹配的對象愚争,takeIf
返回 null映皆,并且不調(diào)用 let
。
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")
}
控制臺輸出:
The substring 11 is found in 010000011.
Its start position is 7.
沒有標準庫函數(shù)時轰枝,相同的函數(shù)看起來是這樣的:
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")
}
使用場景
有這么一種場景可以使用捅彻,如請求后臺返回了一個 UserCallback 對象,需要在界面顯示這個 UserCallback 包含的一個 address 字符串鞍陨,如果返回的 address 如果是 null 或空字符串則顯示“未設置”步淹。
以前這種場景一般都是這樣實現(xiàn)的:
val addr = UserCallback.address
textView.text = if (addr.isNullOrBlank()) "未設置" else addr
但使用 takeIf
或 takeUnless
可以這樣實現(xiàn)更為直接:
textView.text = UserCallback.address.takeUnless { it.isNullOrBlank() }?:"未設置"
// 或者使用takeIf的寫法
// textView.text = UserCallback.address.takeIf { !it.isNullOrBlank() }?:"未設置"