<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 函數 [TOC] ## 函數聲明 Kotlin 中的函數使用 *fun*關鍵字聲明: ```kotlin fun double(x: Int): Int { return 2 * x } ``` ## 函數用法 調用函數使用傳統的方法: ```kotlin val result = double(2) ``` 調用成員函數使用點表示法: ```kotlin Stream().read() // 創建類 Stream 實例并調用 read() ``` ### 參數 函數參數使用 Pascal(帕斯卡) 表示法定義,即 `name: type`。參數用逗號隔開。每個參數必須有顯式類型: ```kotlin fun powerOf(number: Int, exponent: Int) { /*……*/ } ``` ### 默認參數 函數參數可以有默認值,當省略相應的參數時使用默認值。與其他語言相比,這可以減少重載數量: ```kotlin fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) { /*……*/ } ``` 默認值通過類型后面的 **=** 及給出的值來定義。 覆蓋方法總是使用與基類型方法相同的默認參數值。**當覆蓋一個帶有默認參數值的方法時,必須從簽名中省略默認參數值**: ```kotlin open class A { open fun foo(i: Int = 10) { /*……*/ } } class B : A() { override fun foo(i: Int) { /*……*/ } // 不能有默認值 } ``` 如果一個默認參數在一個無默認值的參數之前,那么該默認值只能通過使用[命名參數](http://www.kotlincn.net/docs/reference/functions.html#%E5%91%BD%E5%90%8D%E5%8F%82%E6%95%B0)調用該函數來使用: ```kotlin fun foo(bar: Int = 0, baz: Int) { /*……*/ } foo(baz = 1) // 使用默認值 bar = 0 ``` 如果在默認參數之后的最后一個參數是 [lambda 表達式](http://www.kotlincn.net/docs/reference/lambdas.html#lambda-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%AF%AD%E6%B3%95),那么它既可以作為命名參數在括號內傳入,也可以在[括號外](http://www.kotlincn.net/docs/reference/lambdas.html#%E5%B0%86-lambda-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%BC%A0%E7%BB%99%E6%9C%80%E5%90%8E%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0)傳入(可參考高階函數一小節): ```kotlin fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { /*……*/ } foo(1) { println("hello") } // 使用默認值 baz = 1 foo(qux = { println("hello") }) // 使用兩個默認值 bar = 0 與 baz = 1 foo { println("hello") } // 使用兩個默認值 bar = 0 與 baz = 1 ``` ### 命名參數 可以在調用函數時使用命名的函數參數。當一個函數有大量的參數或默認參數時這會非常方便。 給定以下函數: ```kotlin fun reformat(str: String, normalizeCase: Boolean = true, upperCaseFirstLetter: Boolean = true, divideByCamelHumps: Boolean = false, wordSeparator: Char = ' ') { /*……*/ } ``` 我們可以使用默認參數來調用它: ```kotlin reformat(str) ``` 然而,當使用非默認參數調用它時,該調用看起來就像: ```kotlin reformat(str, true, true, false, '_') ``` 使用命名參數我們可以使代碼更具有可讀性: ```kotlin reformat(str, normalizeCase = true, upperCaseFirstLetter = true, divideByCamelHumps = false, wordSeparator = '_' ) ``` 并且如果我們不需要所有的參數: ```kotlin reformat(str, wordSeparator = '_') ``` **當一個函數調用混用了位置參數與命名參數時,所有位置參數都要放在第一個命名參數之前**。例如,允許調用 `f(1, y = 2)` 但不允許 `f(x = 1, 2)`。 可以通過使用**星號**操作符將[可變數量參數(*vararg*)](http://www.kotlincn.net/docs/reference/functions.html#%E5%8F%AF%E5%8F%98%E6%95%B0%E9%87%8F%E7%9A%84%E5%8F%82%E6%95%B0varargs) 以命名形式傳入: ```kotlin fun foo(vararg strings: String) { /*……*/ } foo(strings = *arrayOf("a", "b", "c")) ``` > **對于 JVM 平臺**:在調用 Java 函數時不能使用命名參數語法,因為 Java 字節碼并不總是保留函數參數的名稱。 > 需要注意的是,在實參中傳遞數組時,需要使用“`*`”前綴操作符,意思是將數組展開,它只能展開數組,不能展開集合。 ### 返回 Unit 的函數 如果一個函數不返回任何有用的值,它的返回類型是 `Unit`。`Unit` 是一種只有一個值——`Unit` 的類型。這個值不需要顯式返回: ```kotlin fun printHello(name: String?): Unit { if (name != null) println("Hello ${name}") else println("Hi there!") // `return Unit` 或者 `return` 是可選的 } ``` `Unit` 返回類型聲明也是可選的。上面的代碼等同于: ```kotlin fun printHello(name: String?) { …… } ``` ### 單表達式函數 當函數返回單個表達式時,可以省略花括號并且在 **=** 符號之后指定代碼體即可: ```kotlin fun double(x: Int): Int = x * 2 ``` 當返回值類型可由編譯器推斷時,顯式聲明返回類型是[可選](http://www.kotlincn.net/docs/reference/functions.html#%E6%98%BE%E5%BC%8F%E8%BF%94%E5%9B%9E%E7%B1%BB%E5%9E%8B)的: ```kotlin fun double(x: Int) = x * 2 ``` ### 顯式返回類型 **具有塊代碼體的函數必須始終顯式指定返回類型,除非他們旨在返回 `Unit`**,[在這種情況下它是可選的](http://www.kotlincn.net/docs/reference/functions.html#%E8%BF%94%E5%9B%9E-unit-%E7%9A%84%E5%87%BD%E6%95%B0)。 **Kotlin 不推斷具有塊代碼體的函數的返回類型,因為這樣的函數在代碼體中可能有復雜的控制流,并且返回類型對于讀者(有時甚至對于編譯器)是不明顯的**。 ### 可變數量的參數(Varargs) 函數的參數(通常是最后一個)可以用 `vararg` 修飾符標記: ```kotlin fun <T> asList(vararg ts: T): List<T> { val result = ArrayList<T>() for (t in ts) // ts is an Array result.add(t) return result } ``` 允許將可變數量的參數傳遞給函數: ```kotlin val list = asList(1, 2, 3) ``` 在函數內部,類型 `T` 的 `vararg` 參數的可見方式是作為 `T` 數組,即上例中的 `ts` 變量具有類型 `Array <out T>`。 只有一個參數可以標注為 `vararg`。如果 `vararg` 參數不是列表中的最后一個參數, 可以使用命名參數語法傳遞其后的參數的值,或者,如果參數具有函數類型,則通過在括號外部傳一個 lambda。 當我們調用 `vararg`-函數時,我們可以一個接一個地傳參,例如 `asList(1, 2, 3)`,或者,如果我們已經有一個數組并希望將其內容傳給該函數,我們使用**伸展(spread)操作符**(在數組前面加 `*`,意識是將數組展開): ```kotlin val a = arrayOf(1, 2, 3) val list = asList(-1, 0, *a, 4) ``` ### 中綴表示法 標有 *infix*關鍵字的函數也可以使用中綴表示法(忽略該調用的點與圓括號)調用。中綴函數必須滿足以下要求: * 它們**必須是成員函數**或[擴展函數](http://www.kotlincn.net/docs/reference/extensions.html); * 它們**必須只有一個參數**; * 其參數不得[接受可變數量的參數](http://www.kotlincn.net/docs/reference/functions.html#%E5%8F%AF%E5%8F%98%E6%95%B0%E9%87%8F%E7%9A%84%E5%8F%82%E6%95%B0varargs)且不能有[默認值](http://www.kotlincn.net/docs/reference/functions.html#%E9%BB%98%E8%AE%A4%E5%8F%82%E6%95%B0)。 ```kotlin infix fun Int.shl(x: Int): Int { …… } // 用中綴表示法調用該函數 1 shl 2 // 等同于這樣 1.shl(2) ``` > 中綴函數調用的優先級低于算術操作符、類型轉換以及 `rangeTo` 操作符。 > 以下表達式是等價的: > * `1 shl 2 + 3` 與 `1 shl (2 + 3)` > * `0 until n * 2` 與 `0 until (n * 2)` > * `xs union ys as Set<*>` 與 `xs union (ys as Set<*>)` > > 另一方面,中綴函數調用的優先級高于布爾操作符 `&&` 與 `||`、`is-` 與 `in-` 檢測以及其他一些操作符。這些表達式也是等價的: > * `a && b xor c` 與 `a && (b xor c)` > * `a xor b in c` 與 `(a xor b) in c` > > 完整的優先級層次結構請參見其[語法參考](http://www.kotlincn.net/docs/reference/grammar.html#expressions)。 請注意,**中綴函數總是要求指定接收者與參數**。當使用中綴表示法在當前接收者上調用方法時,需**要顯式使用 `this`**;不能像常規方法調用那樣省略。這是確保非模糊解析所必需的。 ```kotlin class MyStringCollection { infix fun add(s: String) { /*……*/ } fun build() { this add "abc" // 正確 add("abc") // 正確 //add "abc" // 錯誤:必須指定接收者 } } ``` ## 函數作用域 在 Kotlin 中函數可以在文件頂層聲明,這意味著你不需要像一些語言如 Java、C# 或 Scala 那樣需要創建一個類來保存一個函數。此外除了頂層函數,Kotlin 中函數也可以聲明在局部作用域、作為成員函數以及擴展函數。 ### 局部函數 Kotlin 支持局部函數,即一個函數在另一個函數內部: ```kotlin fun dfs(graph: Graph) { fun dfs(current: Vertex, visited: MutableSet<Vertex>) { if (!visited.add(current)) return for (v in current.neighbors) dfs(v, visited) } dfs(graph.vertices[0], HashSet()) } ``` 局部函數可以訪問外部函數(即閉包)的局部變量,所以在上例中,*visited* 就是外部函數的局部變量: ```kotlin fun dfs(graph: Graph) { val visited = HashSet<Vertex>() fun dfs(current: Vertex) { if (!visited.add(current)) return for (v in current.neighbors) dfs(v) } dfs(graph.vertices[0]) } ``` ### 成員函數 成員函數是在類或對象內部定義的函數: ```kotlin class Sample() { fun foo() { print("Foo") } } ``` 成員函數以點表示法調用: ```kotlin Sample().foo() // 創建類 Sample 實例并調用 foo ``` 關于類和覆蓋成員的更多信息參見[類](http://www.kotlincn.net/docs/reference/classes.html)和[繼承](http://www.kotlincn.net/docs/reference/classes.html#%E7%BB%A7%E6%89%BF)。 ## 泛型函數 函數可以有泛型參數,通過在函數名前使用尖括號指定: ```kotlin fun <T> singletonList(item: T): List<T> { /*……*/ } ``` 關于泛型函數的更多信息參見[泛型](http://www.kotlincn.net/docs/reference/generics.html)。 ## 內聯函數 內聯函數在[這里](http://www.kotlincn.net/docs/reference/inline-functions.html)講述。 ## 擴展函數 擴展函數在[其自有章節](http://www.kotlincn.net/docs/reference/extensions.html)講述。 ## 高階函數和 Lambda 表達式 高階函數和 Lambda 表達式在[其自有章節](http://www.kotlincn.net/docs/reference/lambdas.html)講述。 ## 尾遞歸函數 Kotlin 支持一種稱為[尾遞歸](https://zh.wikipedia.org/wiki/%E5%B0%BE%E8%B0%83%E7%94%A8)的函數式編程風格。 **這允許一些通常用循環寫的算法改用遞歸函數來寫,而無堆棧溢出的風險**。 尾遞歸函數優化:當一個函數用 `tailrec` 修飾符標記并滿足所需的形式時,編譯器會優化該遞歸,留下一個快速而高效的基于循環的版本: ```kotlin val eps = 1E-10 // "good enough", could be 10^-15 tailrec fun findFixPoint(x: Double = 1.0): Double = if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x)) ``` 這段代碼計算余弦的不動點(fixpoint of cosine),這是一個數學常數。 它只是重復地從 1.0 開始調用 Math.cos,直到結果不再改變,對于這里指定的 `eps` 精度會產生 0.7390851332151611 的結果。最終代碼相當于這種更傳統風格的代碼: ```kotlin val eps = 1E-10 // "good enough", could be 10^-15 private fun findFixPoint(): Double { var x = 1.0 while (true) { val y = Math.cos(x) if (Math.abs(x - y) < eps) return x x = Math.cos(x) } } ``` 要符合 `tailrec` 修飾符的條件的話,**函數必須將其自身調用作為它執行的最后一個操作就是尾遞歸**。在遞歸調用后有更多代碼時,不能使用尾遞歸,并**且不能用在 `try/catch/finally` 塊中**。目前在 Kotlin for JVM 與 Kotlin/Native 中支持尾遞歸。
                  <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>

                              哎呀哎呀视频在线观看