跳到主內容

【Kotlin】run , let, apply, also, let

https://developer.android.com/codelabs/java-to-kotlin#0

https://kotlinlang.org/docs/scope-functions.html

功能

物件引用

傳回值

是擴充函數

let

it

Lambda result

Yes

run

this

Lambda result

Yes

run

-

Lambda result

否:在沒有上下文物件的情況下調用

with

this

Lambda result

否:將上下文物件作為參數。

apply

this

Context object

Yes

also

it

Context object

Yes

下面的專門部分提供了有關這些功能的詳細資訊。
以下是根據預期目的選擇作用域函數的簡短指南:

  • 對不可為 null 的物件執行 lambda:let
  • 在局部範圍內引入表達式作為變數:let
  • 物件配置:apply
  • 物件配置和計算結果:run
  • 在需要表達式的地方運行語句:非擴展run
  • 附加效果:also
  • 將物件的函數呼叫進行分組:with

差異

由於作用域函數本質上很相似,因此了解它們之間的差異非常重要。每個作用域函數之間有兩個主要差異:
  • 他們引用上下文物件的方式。
  • 他們的返回值。
fun main() {
    val str = "Hello"
    // this
    str.run {
        println("The string's length: $length")
        //println("The string's length: ${this.length}") // does the same
    }

    // it
    str.let {
        println("The string's length is ${it.length}")
    }
}

this

this

run、with、 並透過關鍵字apply引用上下文物件作為 lambda接收器this。因此,在它們的 lambda 中,物件就像在普通類別函數中一樣可用。


大多數情況下,您可以this在存取接收者物件的成員時省略,從而使程式碼更短。另一方面,如果this省略,則很難區分接收者成員和外部物件或函數。
因此this,對於主要透過呼叫其函數或為屬性賦值來操作物件成員的 lambda,建議將上下文物件作為接收者 ()。
val adam = Person("Adam").apply { 
    age = 20                       // same as this.age = 20
    city = "London"
}
println(adam)
it
反過來,let並also引用上下文物件作為 lambda參數。如果未指定參數名稱,則透過隱式預設名稱存取該物件it。it比 更短this,且 的表達式it通常更容易閱讀。

但是,當呼叫物件的函數或屬性時,您不會像this.因此,it當物件主要用作函數呼叫中的參數時,透過存取上下文物件會更好。it如果在程式碼區塊中使用多個變數也更好。
fun getRandomInt(): Int {
    return Random.nextInt(100).also { value ->
        writeToLog("getRandomInt() generated value $value")
    }
}

val i = getRandomInt()
println(i)
下面的範例示範如何將上下文物件引用為帶有參數名稱的 lambda 參數:value。
傳回值
作用域函數因其傳回的結果而有所不同:
fun getRandomInt(): Int {
    return Random.nextInt(100).also { value ->
        writeToLog("getRandomInt() generated value $value")
    }
}

val i = getRandomInt()
println(i)
apply並also傳回上下文物件。
let、run、 並with回傳 lambda 結果。
您應該根據您接下來想要在程式碼中執行的操作仔細考慮您想要的回傳值。這可以幫助您選擇要使用的最佳範圍函數。
上下文對象
apply和的回傳值also是上下文物件本身。因此,它們可以作為輔助步驟包含在呼叫鏈中:您可以繼續在同一物件上一個接一個地連結函數呼叫。
jjjj

它們也可以用在傳回上下文物件的函數的傳回語句中。

bbbb
Lambda result
let、run、 並with回傳 lambda 結果。因此,您可以在將結果指派給變數、對結果進行連結操作等時使用它們。
sssss
此外,您可以忽略傳回值並使用作用域函數為局部變數建立臨時作用域。
ssss
let

上下文物件可用作參數 ( it)。
傳回值是 lambda 結果。
let可用於在呼叫鏈的結果上呼叫一個或多個函數。例如,以下程式碼列印集合上兩個操作的結果:
dddd
使用let,您可以重寫上面的範例,這樣您就不會將清單操作的結果指派給變數:
dddd
如果傳遞給的程式碼區塊let包含單一函數作為it參數,則可以使用方法來引用 (::) 而不是 lambda 參數:

let通常用於執行包含非空值的程式碼區塊。若要對非空物件執行操作,請對其使用安全呼叫運算子?.let並使用其 lambda 中的操作進行呼叫。

您還可以let引入具有有限範圍的局部變量,以使程式碼更易於閱讀。若要為上下文物件定義新變量,請提供其名稱作為 lambda 參數,以便可以使用它來取代預設值it。

with
上下文物件可用作接收器 (this)。
傳回值是 lambda 結果。
Aswith不是擴展函數:上下文物件作為參數傳遞,但在 lambda 內部,它可用作接收器 (this)。
with當您不需要使用傳回結果時,我們建議使用for 在上下文物件上呼叫函數。在程式碼中,with可以理解為"使用這個對象,執行以下操作。"
fff
您也可以使用with引入一個輔助對象,其屬性或函數用於計算值。
sssss

apply
上下文物件可用作接收器 (this)。
傳回值是物件本身。
由於apply傳回上下文物件本身,我們建議您將其用於不傳回值且主要對接收者物件的成員進行操作的程式碼區塊。最常見的用例apply是物件配置。此類呼叫可以理解為“將以下賦值應用於物件。”
jjj

also
上下文物件可用作參數 (it)。
傳回值是物件本身。
also對於執行一些將上下文物件作為參數的操作很有用。用於also需要引用物件而不是其屬性和函數的操作,或者當您不想隱藏this來自外部範圍的參考時。

當您also在程式碼中看到時,您可以將其讀作"並且還可以對該物件執行以下操作。"
val numbers = mutableListOf("one", "two", "three")
numbers
    .also { println("The list elements before adding new one: $it") }
    .add("four")