<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] # 作用域函數 Kotlin 標準庫包含幾個函數,它們的唯一目的是**在對象的上下文中執行代碼塊**。**當對一個對象調用這樣的函數并提供一個 [lambda 表達式](lambdas.html)時,它會形成一個臨時作用域。在此作用域中,可以訪問該對象而無需其名稱**。這些函數稱為**作用域函數**。共有以下五種:`let`、`run`、`with`、`apply` 以及 `also`。 這些函數基本上做了同樣的事情:**在一個對象上執行一個代碼塊。不同的是這個對象在塊中如何使用,以及整個表達式的結果是什么**。 下面是作用域函數的典型用法 ```kotlin data class Person(var name: String, var age: Int, var city: String) { fun moveTo(newCity: String) { city = newCity } fun incrementAge() { age++ } } fun main() { //sampleStart Person("Alice", 20, "Amsterdam").let { println(it) it.moveTo("London") it.incrementAge() println(it) } //sampleEnd } ``` **如果不使用 `let` 來寫這段代碼,就必須引入一個新變量,并在每次使用它時重復其名稱**。 ```kotlin data class Person(var name: String, var age: Int, var city: String) { fun moveTo(newCity: String) { city = newCity } fun incrementAge() { age++ } } fun main() { //sampleStart val alice = Person("Alice", 20, "Amsterdam") println(alice) alice.moveTo("London") alice.incrementAge() println(alice) //sampleEnd } ``` **作用域函數沒有引入任何新的技術,但是它們可以使你的代碼更加簡潔易讀**。 由于作用域函數的相似性質,為你的案例選擇正確的函數可能有點棘手。選擇主要取決于你的意圖和項目中使用的一致性。下面我們將詳細描述各種作用域函數及其約定用法之間的區別。 ## 區別 由于作用域函數本質上都非常相似,因此了解它們之間的區別很重要。每個作用域函數之間有兩個主要區別: * **引用上下文對象的方式** * **返回值** ### 上下文對象:`this` 還是 `it` **在作用域函數的 lambda 表達式里,上下文對象可以不使用其實際名稱而是使用一個更簡短的引用來訪問**。 每個作用域函數都使用以下兩種方式之一來訪問上下文對象:**作為 lambda 表達式的[接收者](lambdas.html#帶有接收者的函數字面值)(`this`)或者作為 lambda 表達式的參數(`it`)**。兩者都提供了同樣的功能,因此我們將針對不同的場景描述兩者的優缺點,并提供使用建議。 ```kotlin fun main() { val str = "Hello" // this str.run { println("The receiver string length: $length") //println("The receiver string length: ${this.length}") // 和上句效果相同 } // it str.let { println("The receiver string's length is ${it.length}") } } ``` #### this **`run`、`with` 以及 `apply` 通過關鍵字 `this` 引用上下文對象**。因此,在它們的 lambda 表達式中可以像在普通的類函數中一樣訪問上下文對象。**在大多數場景,當你訪問接收者對象時你可以省略 `this`,來讓你的代碼更簡短**。相對地,如果省略了 `this`,就很難區分接收者對象的成員及外部對象或函數。因此,**對于主要對對象成員進行操作(調用其函數或賦值其屬性)的 lambda 表達式,建議將上下文對象作為接收者(`this`)**。 ```kotlin data class Person(var name: String, var age: Int = 0, var city: String = "") fun main() { //sampleStart val adam = Person("Adam").apply { age = 20 // 和 this.age = 20 或者 adam.age = 20 一樣 city = "London" } println(adam) //sampleEnd } ``` #### it 反過來,**`let` 及 `also` 將上下文對象作為 lambda 表達式參數。如果沒有指定參數名,對象可以用隱式默認名稱 `it` 訪問**。`it` 比 `this` 簡短,帶有 `it` 的表達式通常更容易閱讀。然而,當調用對象函數或屬性時,不能像 `this` 這樣隱式地訪問對象。因此,**當上下文對象在作用域中主要用作函數調用中的參數時,使用 `it` 作為上下文對象會更好。若在代碼塊中使用多個變量,則 `it` 也更好**。 ```kotlin import kotlin.random.Random fun writeToLog(message: String) { println("INFO: $message") } fun main() { //sampleStart fun getRandomInt(): Int { return Random.nextInt(100).also { writeToLog("getRandomInt() generated value $it") } } val i = getRandomInt() //sampleEnd } ``` **此外,當將上下文對象作為參數傳遞時,可以為上下文對象指定在作用域內的自定義名稱**。 ```kotlin import kotlin.random.Random fun writeToLog(message: String) { println("INFO: $message") } fun main() { //sampleStart fun getRandomInt(): Int { return Random.nextInt(100).also { value -> writeToLog("getRandomInt() generated value $value") } } val i = getRandomInt() //sampleEnd } ``` ### 返回值 根據返回結果,作用域函數可以分為以下兩類: * **`apply` 及 `also` 返回上下文對象**。 * **`let`、`run` 及 `with` 返回 lambda 表達式結果**. 這兩個選項使你可以根據在代碼中的后續操作來選擇適當的函數。 #### 上下文對象 `apply` 及 `also` 的返回值是上下文對象本身。因此,它們可以作為輔助步驟包含在調用鏈中:你**可以繼續在同一個對象上進行鏈式函數調用**。 ```kotlin fun main() { //sampleStart val numberList = mutableListOf<Double>() numberList.also { println("Populating the list") } .apply { add(2.71) add(3.14) add(1.0) } .also { println("Sorting the list") } .sort() //sampleEnd println(numberList) } ``` 它們**還可以用在返回上下文對象的函數的 return 語句中**。 ```kotlin import kotlin.random.Random fun writeToLog(message: String) { println("INFO: $message") } fun main() { //sampleStart fun getRandomInt(): Int { return Random.nextInt(100).also { writeToLog("getRandomInt() generated value $it") } } val i = getRandomInt() //sampleEnd } ``` #### Lambda 表達式結果 `let`、`run` 及 `with` 返回 lambda 表達式的結果。所以,在**需要使用其結果給一個變量賦值,或者在需要對其結果進行鏈式操作等情況下,可以使用它們**。 ```kotlin fun main() { //sampleStart val numbers = mutableListOf("one", "two", "three") val countEndsWithE = numbers.run { add("four") add("five") count { it.endsWith("e") } } println("There are $countEndsWithE elements that end with e.") //sampleEnd } ``` 此外,**還可以忽略返回值,僅使用作用域函數為變量創建一個臨時作用域**。 ```kotlin fun main() { //sampleStart val numbers = mutableListOf("one", "two", "three") with(numbers) { val firstItem = first() val lastItem = last() println("First item: $firstItem, last item: $lastItem") } //sampleEnd } ``` ## 函數選擇 為了幫助你選擇合適的作用域函數,我們提供了它們之間的主要區別表。 |函數|對象引用|返回值|是否是擴展函數| |---|---|---|---| |`let`|`it`|Lambda 表達式結果|是| |`run`|`this`|Lambda 表達式結果|是| |`run`|-|Lambda 表達式結果|不是:調用無需上下文對象| |`with`|`this`|Lambda 表達式結果|不是:把上下文對象當做參數| |`apply`|`this`|上下文對象|是| |`also`|`it`|上下文對象|是| 以下是根據預期目的選擇作用域函數的簡短指南: * 對一個非空(non-null)對象執行 lambda 表達式:`let` * 將表達式作為變量引入為局部作用域中:`let` * 對象配置:`apply` * 對象配置并且計算結果:`run` * 在需要表達式的地方運行語句:非擴展的 `run` * 附加效果:`also` * **一個對象的一組函數調用**:`with` 不同函數的使用場景存在重疊,你可以根據項目或團隊中使用的特定約定選擇函數。 >[warning]【注意】**盡管作用域函數是使代碼更簡潔的一種方法,但請避免過度使用它們:這會降低代碼的可讀性并可能導致錯誤。避免嵌套作用域函數,同時鏈式調用它們時要小心:此時很容易對當前上下文對象及 `this` 或 `it` 的值感到困惑**。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看