簡體   English   中英

Kotlin:Apply 和 Also 有什么區別

[英]Kotlin: What is the difference between Apply and Also

apply 和 also 有什么區別。 據我所知,下面的代碼做同樣的事情:

申請

val person = Person().apply {
    name = "Tony Stark"
    age = 52
    // More such stuff
}

還有

val person = Person().also {
  it.name = "Tony Stark"
  it.age = 52
  // More such stuff
}

有什么區別嗎,我應該使用一個嗎? 另外,在某些情況下,一個會起作用而另一個不起作用嗎?

TL;DR 差異

also函數采用一個 lambda,您可以在其中使用it (隱式名稱)或自定義名稱來引用您在(接收器T )上調用該函數的對象。

val person = Person().also {
    it.name = "Tony Stark"
}

另一方面,對於apply ,使用帶有接收器的函數文字因此在傳入的 lambda 中,您可以直接訪問接收器的成員,如下所示。 可以通過this引用接收器。

val person = Person().apply {
    name = "Tony Stark"
}

還有

聲明:

inline fun <T> T.also(block: (T) -> Unit): T (source)

使用this (接收器)值作為其參數調用指定的功能塊並返回this (接收器)值。

申請

聲明:

inline fun <T> T.apply(block: T.() -> Unit): T (source)

使用this值作為其接收者調用指定的功能塊並返回this (接收者)值。

什么時候用什么

線程中解釋了使用示例。

簡短回答: also出於語義原因引入的。

長答案:

如果你使用apply你總是用this來指代接收者。

val person = Person().apply {
    name = "Tony Stark" // this. can be omitted
    age = 52 // this. can be omitted
    // ...
}

這樣您就不必多次重復 person ,如下所示:

person.name = "Tony Stark"
person.age = 52

如果塊變長,你可能想給this一個名字。 這就是為什么also被介紹了。 現在您可以通過it或一個明確的名稱來引用接收器。 如果您想使用之前的其他名稱(在本例中為person ),這將特別有用:

val person = Person().also { newPerson ->
  newPerson.name = "Tony Stark"
  newPerson.age = 52
  // ...
}

因此,根據您的代碼可讀性如何,您始終可以使用其中一種。

  • 這兩個函數都返回接收者對象本身。
  • 它們在訪問接收器對象方面有所不同。

在此處輸入圖片說明

使用哪一個由您決定。 但是,在 Kotlinlang 的網站https://kotlinlang.org/docs/reference/scope-functions.html 中,它們的用法有一個約定

用於不改變對象的其他操作,例如記錄或打印調試信息。

val numbers = mutableListOf("one", "two", "three")
 numbers
     .also { println("The list elements before adding new one: $it") }
     .add("four")

apply的常見情況是對象配置。

val adam = Person("Adam").apply {
    age = 32
    city = "London"        
}
println(adam)

上面給出的答案有點意義,但並不多。 我不理解它,但我想在這里補充問題。

在Standard.kt中,這是兩種方法的實際實現。

申請

/**
 * Calls the specified function [block] with `this` value as its receiver and returns `this` value.
 */
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

也是

/**
 * Calls the specified function [block] with `this` value as its argument and returns `this` value.
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}

除了一行之外,這兩種方法幾乎相同。 只有經過解釋后,我才看到了不同之處。 像Kotlin這樣的功能語言對於像我這樣的Java思想的初級開發人員來說真的很有挑戰性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM