<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      kotlin函數(shù)和Lambda表達(dá)式——>高階函數(shù)與lambda表達(dá)式

      1.高階函數(shù)

         高階函數(shù)是將函數(shù)用作參數(shù)或返回值的函數(shù)。

        一個(gè)不錯(cuò)的示例是集合的函數(shù)式?格的 fold,它接受一個(gè)初始累積值與一個(gè)接合函數(shù),并通過(guò)將當(dāng)前 累積值與每個(gè)集合元素連續(xù)接合起來(lái)代入累積值來(lái)構(gòu)建返回值:

      fun <T, R> Collection<T>.fold(
              initial: R,
              combine: (acc: R, nextElement: T) -> R
      ): R {
          var accumulator: R = initial
          for (element: T in this) {
              accumulator = combine(accumulator, element)
          }
          return accumulator
      }
      //在上述代碼中,參數(shù)combine 具有函數(shù)類型 (R, T) -> R ,因此 fold 接受一個(gè)函數(shù)作為參數(shù),該函數(shù)接受類型分別為 R 與 T 的兩個(gè)參數(shù)并返回一個(gè) R 類型的值。
      // 在 for-循環(huán)內(nèi)部調(diào)用該函數(shù),然后 將其返回值賦值給 accumulator 。

        為了調(diào)用 fold,需要傳給它一個(gè)函數(shù)類型的實(shí)例作為參數(shù),而在高階函數(shù)調(diào)用處,(下文詳述 的)lambda 表達(dá) 式廣泛用于此目的。

      val items = listOf(1, 2, 3, 4, 5)
      // Lambdas 表達(dá)式是花括號(hào)括起來(lái)的代碼塊。 
      items.fold(0, {
          // 如果一個(gè) lambda 表達(dá)式有參數(shù),前面是參數(shù),后跟“->”
          acc: Int, i: Int ->
          print("acc = $acc, i = $i, ")
          val result = acc + i
          println("result = $result")
          // lambda 表達(dá)式中的最后一個(gè)表達(dá)式是返回值:
          result
      })
      // lambda 表達(dá)式的參數(shù)類型是可選的,如果能夠推斷出來(lái)的話:
      val joinedToString = items.fold("Elements:", { acc, i -> acc + " " + i })
      
      // 函數(shù)引用也可以用于高階函數(shù)調(diào)用:
      val product = items.fold(1, Int::times)

       

      2.函數(shù)類型

        Kotlin 使用類似 (Int) -> String 的一系列函數(shù)類型來(lái)處理函數(shù)的聲明:val onClick: () - > Unit = ......。

      //這些類型具有與函數(shù)簽名相對(duì)應(yīng)的特殊表示法,即它們的參數(shù)和返回值:
      //— 所有函數(shù)類型都有一個(gè)圓括號(hào)括起來(lái)的參數(shù)類型列表以及一個(gè)返回類型:(A, B) -> C 表示接受 類型分別為 A 與 B 兩個(gè)參數(shù)并返回一個(gè) C 類型值的函數(shù)類型。參數(shù)類型列表可以為空,如 () - > A。Unit返回類型不可省略。
      //— 函數(shù)類型可以有一個(gè)額外的接收者類型,它在表示法中的點(diǎn)之前指定:類型 A.(B) -> C 表示可 以在 A 的接收者對(duì)象上以一個(gè) B 類型參數(shù)來(lái)調(diào)用并返回一個(gè) C 類型值的函數(shù)。帶有接收者的函 數(shù)字面值通常與這些類型一起使用。
      //— 掛起函數(shù)屬于特殊種類的函數(shù)類型,它的表示法中有一個(gè) suspend 修飾符 ,例如 suspend () - > Unit 或者 suspend A.(B) -> C 。

        函數(shù)類型表示法可以選擇性地包含函數(shù)的參數(shù)名:(x: Int, y: Int) -> Point 。這些名稱可用于表明參數(shù)的含義。

      //如需將函數(shù)類型指定為可空,請(qǐng)使用圓括號(hào):((Int, Int) -> Int)?。
      //函數(shù)類型可以使用圓括號(hào)進(jìn)行接合:(Int) -> ((Int) -> Unit)
      //箭頭表示法是右結(jié)合的,(Int) -> (Int) -> Unit 與前述示例等價(jià),但不等于 ((Int) -> (Int)) -> Unit。

        還可以通過(guò)使用類型別名給函數(shù)類型起一個(gè)別稱:

      typealias ClickHandler = (Button, ClickEvent) -> Unit

       

      3.函數(shù)類型實(shí)例化

        有幾種方法可以獲得函數(shù)類型的實(shí)例:

      //— 使用函數(shù)字面值的代碼塊,采用以下形式之一:
          //— lambda表達(dá)式:{a,b->a+b},
          //— 匿名函數(shù): fun(s: String): Int { return s.toIntOrNull() ?: 0 }
      //帶有接收者的函數(shù)字面值可用作帶有接收者的函數(shù)類型的值。
      //— 使用已有聲明的可調(diào)用引用:
          //— 頂層、局部、成員、擴(kuò)展函數(shù):::isOdd、String::toInt,
          //— 頂層、成員、擴(kuò)展屬性:List<Int>::size
          //— 構(gòu)造函數(shù):::Regex
          //這包括指向特定實(shí)例成員的綁定的可調(diào)用引用:foo::toString 。 

        — 使用實(shí)現(xiàn)函數(shù)類型接口的自定義類的實(shí)例:

      class IntTransformer: (Int) -> Int {
          override operator fun invoke(x: Int): Int = TODO()
      }
      val intFunction: (Int) -> Int = IntTransformer()

         如果有足夠信息,編譯器可以推斷變量的函數(shù)類型:

      val a = { i: Int -> i + 1 } // 推斷出的類型是 (Int) -> Int

        帶與不帶接收者的函數(shù)類型非字面值可以互換,其中接收者可以替代第一個(gè)參數(shù),反之亦然。例如,(A,B) -> C 類型的值可以傳給或賦值給期待 A.(B) -> C 的地方,反之亦然

       val repeatFun: String.(Int) -> String = { times -> this.repeat(times) }
          val twoParameters: (String, Int) -> String = repeatFun // OK
          fun runTransformation(f: (String, Int) -> String): String {
              return f("hello", 3)
          }
      
          val result = runTransformation(repeatFun) // OK 

      //
      請(qǐng)注意,默認(rèn)情況下推斷出的是沒(méi)有接收者的函數(shù)類型,即使變量是通過(guò)擴(kuò)展函數(shù)引用來(lái)初始化 的。如需改變這點(diǎn),請(qǐng)顯式指定變量類型。

      4.函數(shù)類型實(shí)例調(diào)用

        函數(shù)類型的值可以通過(guò)其 invoke(......) 操作符調(diào)用:f.invoke(x) 或者直接 f(x)

        如果該值具有接收者類型,那么應(yīng)該將接收者對(duì)象作為第一個(gè)參數(shù)傳遞。調(diào)用帶有接收者的函數(shù)類型值的另一個(gè)方式是在其前面加上接收者對(duì)象,就好比該值是一個(gè)擴(kuò)展函數(shù):1.foo(2) 例如:

          val stringPlus: (String, String) -> String = String::plus
          val intPlus: Int.(Int) -> Int = Int::plus
          println(stringPlus.invoke("<-", "->"))
          println (stringPlus("Hello, ", "world!"))
          println(intPlus.invoke(1, 1))
          println (intPlus(1, 2))
          println (2.intPlus(3)) // 類擴(kuò)展調(diào)用

      5.內(nèi)聯(lián)函數(shù),有時(shí)使用內(nèi)聯(lián)函數(shù)可以為高階函數(shù)提供靈活的控制流

      6.Lambda表達(dá)式與匿名函數(shù)

        lambda 表達(dá)式與匿名函數(shù)是“函數(shù)字面值”,即未聲明的函數(shù),但立即做為表達(dá)式傳遞。考慮下面的例子:

      max(strings, { a, b -> a.length < b.length })

        函數(shù) max 是一個(gè)高階函數(shù),它接受一個(gè)函數(shù)作為第二個(gè)參數(shù)。其第二個(gè)參數(shù)是一個(gè)表達(dá)式,它本身是 一個(gè)函數(shù),即函數(shù)字面值,它等價(jià)于以下具名函數(shù):

      fun compare(a: String, b: String): Boolean = a.length < b.length

      7.Lambda表達(dá)式語(yǔ)法

        Lambda 表達(dá)式的完整語(yǔ)法形式如下:

      val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }

        lambda 表達(dá)式總是括在花括號(hào)中,完整語(yǔ)法形式的參數(shù)聲明放在花括號(hào)內(nèi),并有可選的類型標(biāo)注,函數(shù)體跟在一個(gè) -> 符號(hào)之后。如果推斷出的該 lambda 的返回類型不是 Unit ,那么該 lambda 主體中 的最后一個(gè)(或可能是單個(gè))表達(dá)式會(huì)視為返回值。

        如果我們把所有可選標(biāo)注都留下,看起來(lái)如下:

      val sum = { x: Int, y: Int -> x + y }

      8.傳遞末尾的lambda表達(dá)式

        在 Kotlin 中有一個(gè)約定:如果函數(shù)的最后一個(gè)參數(shù)是函數(shù),那么作為相應(yīng)參數(shù)傳入的 lambda 表達(dá)式可以放在圓括號(hào)之外:

      val product = items.fold(1) { acc, e -> acc * e }
      //這種語(yǔ)法也稱為拖尾 lambda 表達(dá)式。

        如果該 lambda 表達(dá)式是調(diào)用時(shí)唯一的參數(shù),那么圓括號(hào)可以完全省略:

      run { println("...") }

      9.it:單個(gè)參數(shù)的隱式名稱

        一個(gè) lambda 表達(dá)式只有一個(gè)參數(shù)是很常?的。 如果編譯器自己可以識(shí)別出簽名,也可以不用聲明唯一的參數(shù)并忽略 -> 。該參數(shù)會(huì)隱式聲明為 it :

      ints.filter { it > 0 } // 這個(gè)字面值是“(it: Int) -> Boolean”類型的

      10.從lambda表達(dá)式中返回一個(gè)值

        我們可以使用限定的返回語(yǔ)法從 lambda 顯式返回一個(gè)值。否則,將隱式返回最后一個(gè)表達(dá)式的值。 因此,以下兩個(gè)片段是等價(jià)的:

          ints.filter {
              val shouldFilter = it > 0 
              shouldFilter
          }
          ints.filter {
              val shouldFilter = it > 0 
              return@filter shouldFilter
          }

        這一約定連同在圓括號(hào)外傳遞 lambda 表達(dá)式一起支持 LINQ-?格 的代碼:

      strings.filter { it.length == 5 }.sortedBy { it }.map { it.toUpperCase() }

      11.下劃線用于未使用的變量(1.1起)

        如果 lambda 表達(dá)式的參數(shù)未使用,那么可以用下劃線取代其名稱:

      map.forEach { _, value -> println("$value!") }

      12.匿名函數(shù)

        上面提供的 lambda 表達(dá)式語(yǔ)法缺少的一個(gè)東西是指定函數(shù)的返回類型的能力。在大多數(shù)情況下,這是 不必要的。因?yàn)榉祷仡愋涂梢宰詣?dòng)推斷出來(lái)。然而,如果確實(shí)需要顯式指定,可以使用另一種語(yǔ)法:匿名 函數(shù) 。

      fun(x: Int, y: Int): Int = x + y

        匿名函數(shù)看起來(lái)非常像一個(gè)常規(guī)函數(shù)聲明,除了其名稱省略了。其函數(shù)體可以是表達(dá)式(如上所示)或代

      碼塊

      fun(x: Int, y: Int): Int {
              return x + y
      }

        參數(shù)和返回類型的指定方式與常規(guī)函數(shù)相同,除了能夠從上下文推斷出的參數(shù)類型可以省略

      ints.filter(fun(item) = item > 0)

        匿名函數(shù)的返回類型推斷機(jī)制與正常函數(shù)一樣:對(duì)于具有表達(dá)式函數(shù)體的匿名函數(shù)將自動(dòng)推斷返回類

      型,而具有代碼塊函數(shù)體的返回類型必須顯式指定(或者已假定為 Unit)。

         請(qǐng)注意,匿名函數(shù)參數(shù)總是在括號(hào)內(nèi)傳遞。允許將函數(shù)留在圓括號(hào)外的簡(jiǎn)寫(xiě)語(yǔ)法僅適用于 lambda 表達(dá)

      式。

        Lambda表達(dá)式與匿名函數(shù)之間的另一個(gè)區(qū)別是非局部返回的行為。一個(gè)不帶標(biāo)簽的 return 語(yǔ)句總 是在用 fun 關(guān)鍵字聲明的函數(shù)中返回。這意味著 lambda 表達(dá)式中的 return 將從包含它的函數(shù)返回, 而匿名函數(shù)中的 return 將從匿名函數(shù)自身返回。

      13.閉包

        Lambda 表達(dá)式或者匿名函數(shù)(以及局部函數(shù)和對(duì)象表達(dá)式)可以訪問(wèn)其 閉包 ,即在外部作用域中聲明 的變量。在 lambda 表達(dá)式中可以修改閉包中捕獲的變量:

      14.帶有接收者的函數(shù)字面值

        帶有接收者的函數(shù)類型,例如 A.(B) -> C ,可以用特殊形式的函數(shù)字面值實(shí)例化? 帶有接收者的 函數(shù)字面值。

        如上所述,Kotlin 提供了調(diào)用帶有接收者(提供接收者對(duì)象)的函數(shù)類型實(shí)例的能力。 在這樣的函數(shù)字面值內(nèi)部,傳給調(diào)用的接收者對(duì)象成為隱式的this,以便訪問(wèn)接收者對(duì)象的成員而無(wú)需

      任何額外的限定符,亦可使用 this 表達(dá)式 訪問(wèn)接收者對(duì)象。

        這種行為與擴(kuò)展函數(shù)類似,擴(kuò)展函數(shù)也允許在函數(shù)體內(nèi)部訪問(wèn)接收者對(duì)象的成員。 這里有一個(gè)帶有接收者的函數(shù)字面值及其類型的示例,其中在接收者對(duì)象上調(diào)用了 plus

      val sum: Int.(Int) -> Int = { other -> plus(other) }

        匿名函數(shù)語(yǔ)法允許你直接指定函數(shù)字面值的接收者類型。如果你需要使用帶接收者的函數(shù)類型聲明一個(gè)變量,并在之后使用它,這將非常有用

      val sum = fun Int.(other: Int): Int = this + other

        當(dāng)接收者類型可以從上下文推斷時(shí),lambda 表達(dá)式可以用作帶接收者的函數(shù)字面值。One of the most important examples of their usage is type-safe builders:

          class HTML {
              fun body() {
                  ......
              }
          }
      
          fun html(init: HTML.() -> Unit): HTML {
              val html = HTML() // 創(chuàng)建接收者對(duì)象
              html.init() // 將該接收者對(duì)象傳給該 lambda 
              return html
          }
          html { // 帶接收者的 lambda 由此開(kāi)始
              body() 
              // 調(diào)用該接收者對(duì)象的一個(gè)方法
          }

       

       

       

      posted @ 2020-06-30 18:06  王世楨  閱讀(422)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产成人精品无码播放| 亚洲第一尤物视频在线观看导航| 国产熟妇久久777777| 久久精品国产亚洲成人av| 亚洲精中文字幕二区三区| 综合色在线| 成人特黄特色毛片免费看| 在线看国产精品自拍内射| 一个人在看www免费| 成人亚洲av免费在线| 国产做a爱片久久毛片a片| 成人国产精品中文字幕| 久久99精品国产麻豆婷婷| 国产精品麻豆va在线播放| 国产精品国产三级国快看| 一区二区三区无码免费看| japanese无码中文字幕| 中文字幕av无码一区二区蜜芽三区| 亚洲精品二区在线播放| 四虎永久地址www成人| 91国产自拍一区二区三区| 一区二区不卡国产精品| 日本高清aⅴ毛片免费| 视频一区视频二区中文字幕| 免费AV片在线观看网址| 国产无吗一区二区三区在线欢| 四虎国产成人永久精品免费| 小嫩批日出水无码视频免费| 国产精品天天在线午夜更新| 综合区一区二区三区狠狠| 97夜夜澡人人爽人人模人人喊| 万载县| 国产 麻豆 日韩 欧美 久久| 亚洲AV无码精品色午夜果冻| 99久久精品费精品国产一区二| 午夜AAAAA级岛国福利在线| 理论片午午伦夜理片久久| 国产一区二区日韩经典| 99在线小视频| 人妻无码不卡中文字幕系列| 国产一区二区三区导航|