在Kotlin的標(biāo)準(zhǔn)函數(shù)球散,有兩大函數(shù),即takeIf
和takeUnless
,乍一看搓蚪,有什么特別之處呢郭蕉?這幾乎就是if
疼邀?
或者極端點(diǎn),把每一個(gè)if
語(yǔ)句改成類似下面(不推薦)召锈。
//原始代碼
if(status){doThis()}
//修改后的代碼
takeIf {status}旁振?apply {doThis()}
深入探討
像其他任何東西一樣,takeIf
(或takeUnless
)確實(shí)有它的使用場(chǎng)景烟勋。我通過不同情況分享我對(duì)他們的理解规求。在此之前,讓我們看看它的實(shí)現(xiàn)卵惦。
函數(shù)簽名
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T?
= if (predicate(this)) this else null
從函數(shù)簽名,我們注意到
- 它是從T對(duì)象本身調(diào)用的瓦戚。即
T.takeIf
沮尿, -
predicate
函數(shù)以T對(duì)象為參數(shù) - 等待
predicate
評(píng)估后它返回this
或null
。
合理的使用情況
基于以上特點(diǎn)较解,我可以推導(dǎo)出它相對(duì)于if
的使用情況畜疾,如下:
1.它是從T對(duì)象本身調(diào)用的。即T.takeIf
印衔,
它可以很好處理可空性檢查啡捶。一個(gè)例子如下
//原始代碼
if(someObject!= null && status){
doThis()
}
//改進(jìn)的代碼
someObject奸焙?.takeIf {status}瞎暑?apply {doThis()}
2.predicate
函數(shù)以T對(duì)象為參數(shù)
由于將T作為predicate
的參數(shù),所以可以進(jìn)一步簡(jiǎn)化takeIf
代碼
//原始代碼
if(someObject与帆!= null && someObject.status){
doThis()
}
//更好的代碼
if(someObject了赌?.status == true){
doThis()
}
//改進(jìn)的代碼
someObject?.takeIf {it.status} ?. apply {doThis()}
更好的代碼
的確還可以玄糟,但需要顯式的true
關(guān)鍵詞勿她,所以并不理想。
3.等待predicate
評(píng)估后它返回this
或null
既然它返回this
阵翎,那就可以用來進(jìn)行鏈?zhǔn)秸{(diào)用逢并。因此,下面代碼可以優(yōu)化
//原始代碼
if(someObject郭卫!= null && someObject.status){
someObject.doThis()
}
//改進(jìn)的代碼
someObject砍聊?.takeIf {status}?doThis()
或者實(shí)現(xiàn)獲取數(shù)據(jù)或退出的更好方式(例子從Kotlin Doc中摘认渎佟)
val index
= input.indexOf(keyword).takeIf {it> = 0}辩恼?:error(“Error”)
val outFile
= File(outputDir.path).takeIf {it.exists()}?:return false
注意
看看下面的代碼。
//語(yǔ)法上仍然正確灶伊。但邏輯錯(cuò)誤疆前!
someObject?.takeIf {status} .apply {doThis()}
//正確的(注意可空性檢查聘萨?)
someObject竹椒?.takeIf {status} ?.apply {doThis()}
doThis()
在第一行中不管status
true 還是 false 都會(huì)執(zhí)行米辐。因?yàn)?即使takeIf
返回null
胸完,它仍然會(huì)被調(diào)用。(這里假設(shè)doThis()
不是someObject
的函數(shù))
所以在這里翘贮,第二行的?
是非常微妙且重要的赊窥。