使用Kotlin takeIf(或takeUnless)

原文連接html

在Kotlin的標準函數,有兩大函數,即takeIftakeUnless,乍一看,有什麼特別之處呢?這幾乎就是ifgit

或者極端點,把每個if語句改爲相似下面(推薦)。github

//原始代碼
if(status){doThis()}
//修改後的代碼
takeIf {status}?apply {doThis()}
複製代碼

深刻探討

像其餘任何東西同樣,takeIf(或takeUnless)確實有它的使用場景。我經過不一樣狀況分享我對他們的理解。在此以前,讓咱們看看它的實現。bash

函數簽名

public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? 
    = if (predicate(this)) this else null
複製代碼

從函數簽名,咱們注意到app

  1. 它是從T對象自己調用的。即T.takeIf
  2. predicate函數以T對象爲參數
  3. 等待predicate評估後它返回thisnull

合理的使用狀況

基於以上特色,我能夠推導出它相對於if的使用狀況,以下:less

1.它是從T對象自己調用的。即T.takeIf

它能夠很好處理可空性檢查。一個例子以下函數

//原始代碼
if(someObject!= null && status){ 
   doThis()
}
//改進的代碼
someObject?.takeIf {status}?apply {doThis()}
複製代碼

2.predicate函數以T對象爲參數

因爲將T做爲predicate的參數,因此能夠進一步簡化takeIf代碼優化

//原始代碼
if(someObject!= null && someObject.status){ 
   doThis()
} 
//更好的代碼
if(someObject?.status == true){ 
   doThis()
}
//改進的代碼
someObject?.takeIf {it.status} ?. apply {doThis()}
複製代碼

更好的代碼的確還能夠,但須要顯式的true關鍵詞,因此並不理想。this

3.等待predicate評估後它返回thisnull

既然它返回this,那就能夠用來進行鏈式調用。所以,下面代碼能夠優化spa

//原始代碼
if(someObject!= null && someObject.status){ 
   someObject.doThis()
}
//改進的代碼
someObject?.takeIf {status}?doThis()
複製代碼

或者實現獲取數據或退出的更好方式(例子從Kotlin Doc中摘取)

val index 
   = input.indexOf(keyword).takeIf {it> = 0}?:error(「Error」)
val outFile 
   = File(outputDir.path).takeIf {it.exists()}?:return  false
複製代碼

注意

看看下面的代碼。

//語法上仍然正確。但邏輯錯誤!
someObject?.takeIf {status} .apply {doThis()}

//正確的(注意可空性檢查?)
someObject?.takeIf {status} ?.apply {doThis()}
複製代碼

doThis()在第一行中無論statustrue 仍是 false 都會執行。由於 即便takeIf返回null,它仍然會被調用。(這裏假設doThis()不是someObject的函數)

因此在這裏,第二行的? 是很是微妙且重要的。

相關文章
相關標籤/搜索