在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 或者 省略 | 返回調用者對象 |