Kotlin常用函數let、with、run、apply的用法和區別

在kotlin編程中let、with、run、apply這些函數使用率是非常高的,有時候可以通用,差別很小,但如果能記住他們的不同點,可以更加合理的選擇使用。

在這之前首先要了解一下Lambda表達式的一些規則,這會幫助你理解使用這些函數的時候有沒有( )可不可以用it代替參數等。因爲這些函數的最後一個參數都是lambda。

如何理解lambda呢?可以把lambda理解爲就是一個對象,但這個對象比較特殊,它是一段代碼,既然是對象就可以作爲函數的參數使用。這種對象稱爲函數對象。
lambda表達式的語法格式舉例:
{ x: Int, y: Int -> x + y }
lambda 表達式是括在“{ }”中, “ ->” 前面爲lambda參數,後面爲函數體。爲了方便理解用普通函數推導一下變化過程:

fun sum(x: Int, y: Int) = x + y

首先去掉了關鍵字fun和方法名:

(x: Int, y: Int) = x + y

之後分爲了2部分,“=” 前面作爲lambda參數,後面作爲函數體,中間用“->” 代替:

(x: Int, y: Int) ->  x + y

最後去掉參數的小括號,在外面加上大括號:

{x: Int, y: Int ->  x + y}

最終得到的lambda表達式就可以作爲參數使用了:

fun useLambda(a: Int, {x: Int, y: Int ->  x + y}){
  ...代碼省略...
}

瞭解了基礎的語法格式後,在來看下,lambda的幾個重要規則:
Kotlin規則1:如果函數的最後一個參數是lambda,lambda 表達式可以放在圓括號之外(拖尾 lambda):

val result = useLambda(a: Int){x: Int, y: Int ->  x + y}

Kotlin規則2:如果函數只有lambda一個參數時候,圓括號可以省略:

修改了useLambda函數:
fun useLambda({str: String ->  str.length}){
  ...代碼省略...
}
規則1改爲:
val result = useLambda(){str: String ->  str.length}
規則2改爲:
val result = useLambda{str: String ->  str.length}

Kotlin規則3:如果lambda表達式只有一個參數時候,不用聲明參數,可以用隱式名稱it代替參數:

val result = useLambda{it.length}

Kotlin規則4:lambda表達式中有參數未使用的時候,可用下劃線“_” 代替

useLambda(){_, y ->  x * x}

瞭解了lambda表達式之後再來分析函數
let函數用法:

val result = obj.let {
   //TODO 使用it訪問obj對象的方法或者屬性
   it.xxx()
   //TODO 最後一行代碼的結果爲返回值賦值給result
}

從let函數寫法和lambda的規則可以看出,它只有一個lambda參數,並且這個lambda的參數也只有一個,就是調用者對象本身。let最常用於判斷對象空指針之後有連續操作的場景。舉例:

obj?.let{
   it.dosomething1()
   it.dosomething2()
   it.dosomething3()
}

with函數用法:

val result = with(obj) {
//TODO 直接訪問obj對象的方法或者屬性,或者使用this.調用
//TODO 最後一行代碼的結果爲返回值賦值給result
}

同樣我們可以看出,with函數有2個參數,第一個參數爲要處理的對象,最後一個是lambda參數,根據規則1,放在了圓括號後邊。在這個lambda表達式中提供了第一個參數的對象可以用this指定,也可以省略。

run函數用法:

val result = obj.run{
//TODO 直接訪問obj對象的方法或者屬性,或者使用this.調用
//TODO 最後一行代碼的結果爲返回值賦值給result
}

run函數只有一個lambda參數,run看上去是let與with的結合。因爲run可以解決判空調用還可以去掉“it”解決let函數隱式名稱調用問題。

apply函數用法:

val result = obj.apply{
//TODO 直接訪問obj對象的方法或者屬性,或者使用this.調用
}

可以看出與run函數幾乎一樣,唯一的區別是lambda中沒有指定返回值。返回的是調用者對象本身,也就是obj。

總結:

函數 參數個數 內部訪問上下文對象 返回值
let 1 it lambda最後一行代碼返回值
with 2 this 或者 省略 lambda最後一行代碼返回值
run 1 this 或者 省略 lambda最後一行代碼返回值
apply 1 this 或者 省略 返回調用者對象
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章