kotlin:高階函數(shù)和lambda表達(dá)式

  1. 高階函數(shù):kotlin提供的一種特殊的函數(shù),可以將函數(shù)作為參數(shù)傳入或者將函數(shù)作為返回值返回。
    • kotlin系統(tǒng)函數(shù)中提供了一系列的高階函數(shù),比如kotlin中的集合的操作函數(shù),kotlin中的高階函數(shù):let,with,apply,use幾個函數(shù)(當(dāng)前文章著重學(xué)習(xí)高階函數(shù)和lambda表達(dá)式,具體的高階函數(shù)后續(xù)新開文章學(xué)習(xí)總結(jié)),即:


      kotlin高階函數(shù)

      集合的fold函數(shù)

      fold函數(shù)使用
  2. 函數(shù)類型(Function Type)
    • 結(jié)合高階函數(shù),將函數(shù)作為參數(shù)或者作為返回類型,為了支持這種實(shí)現(xiàn)kotlin提供了函數(shù)類型這一概念并聲明了函數(shù)類型的語法,整理如下:
      • 語法:(參數(shù)類型列表)-> 返回值類型:注意基礎(chǔ)的函數(shù)類型的是參數(shù)類型列表,實(shí)例:(Int,Int)-> Int : 接受兩個Int的參數(shù),返回一個Int的返回值。
        • 參數(shù)的個數(shù)可以為null,即此時的語法() -> Int:沒有參數(shù)返回一個Int的值,也可以沒有返回值,即()-> Unit :此時需要注意的是Unit不能省略。
        • A.(B) -> C:函數(shù)類型提供一個接受者:即:表示一個可以對類型為 A 的接受者調(diào)用的函數(shù), 參數(shù)類型為B, 返回值類型為 C. 對這種函數(shù)類型, 我們經(jīng)常使用 帶接受者的函數(shù)字面值。
          帶有接受者的函數(shù)類型
        • 掛起函數(shù)(Suspending function)是一種特殊類型的函數(shù), 它的聲明帶有一個特殊的 suspend 修飾符, 比如: suspend () -> Unit, 或者: suspend A.(B) -> C.
        • 帶有參數(shù)名的參數(shù)列表:參數(shù)列表中可以只是參數(shù)類型 , 也可以加上參數(shù)的變量名稱 , 參數(shù)名稱可以用于說明參數(shù)的含義 , 增加函數(shù)類型的理解性


          帶有參數(shù)名稱的參數(shù)類型
        • 函數(shù)類型可空:函數(shù)類型 與 普通變量類型一樣 , 也分為可空類型 , 非空類型 兩類 。默認(rèn)的函數(shù)類型都是非空類型 , 即函數(shù)定義時 , 需要對其進(jìn)行初始化 , 或延遲初始化 ??煽盏暮瘮?shù)類型聲明時 , 需要在函數(shù)類型外部加上括號 , 并在右側(cè)添加 ? 可空符號 :
          ( ( 參數(shù)列表 ) -> 返回值類型 ) ?


          可空函數(shù)類型
          • 函數(shù)類型也可以使用括號組合在一起: (Int) -> ((Int) -> Unit)


            嵌套函數(shù)類型
          • 可以給函數(shù)類型指定別名:typealias ClickHandler = (Button, ClickEvent) -> Unit
          • 函數(shù)類型的實(shí)例化:lambda表達(dá)式,匿名函數(shù),已聲明的函數(shù),函數(shù)變量,函數(shù)類型派生類。
            • lambda表達(dá)式:val add1:(Int,Int) -> Int = {a:Int,b:Int -> a+b}:語法上需要注意的是:函數(shù)類型的語法:()-> Int lambda表達(dá)式的語法:{a:Int,b:Int -> a+b},整體的理解: 變量關(guān)鍵字 變量名:()-> 返回值類型,Int = {a:Int,b:Int -> a+b} 整個是返回值類型。
            • 匿名函數(shù):var add2 : (Int, Int) -> Int = fun (a : Int, b : Int) : Int {return a + b}
            • 已聲明的函數(shù):需要注意的是::的使用方式,頂層函數(shù)可以直接使用:: 類中的函數(shù)使用類::函數(shù)來實(shí)例化函數(shù)類型后給變量。


              通過已聲明的函數(shù)來實(shí)例化函數(shù)類型
            • 函數(shù)變量:已經(jīng)聲明的函數(shù)類型屬性 , 可以是頂層屬性 , 成員屬性 , 擴(kuò)展屬性 即:


              函數(shù)變量初始化函數(shù)類型
            • 函數(shù)類型的派生類:我去直接拿一個類實(shí)現(xiàn)一個函數(shù)類型,在其重寫函數(shù)invoke中返回數(shù)值類型,函數(shù)類型可以看做一個接口 , 類可以實(shí)現(xiàn)該接口 , 在實(shí)現(xiàn)類中實(shí)現(xiàn)具體的函數(shù)操作 , 該 函數(shù)類型接口的實(shí)現(xiàn)類 , 可以賦值給函數(shù)類型變量


              函數(shù)類型派生類實(shí)例化函數(shù)類型
              • 針對上面這幾項(xiàng)可以參考下面的參考文章,參考文章說明的更詳細(xì)包括事例更有代表性。
            • 函數(shù)類型的自動推斷:像kotlin的參數(shù)似的,kotlin可以根據(jù)第一次賦值推斷出參數(shù)的類型,所以可以不直接指定參數(shù)的類型,函數(shù)類型的返回值類型,kotlin也可以通過lambda或者匿名函數(shù)或者其他幾種實(shí)例化方式推斷出返回值的類型,還有函數(shù)類型的參數(shù)類型也可以通過lambda幾種實(shí)例化進(jìn)而推斷出類型,所以二者都可以省略,需要注意的是kotlin推斷不出其對應(yīng)的類型的時候 參數(shù)類型和返回值類型都不能省略。比如Unit不能夠省略。


              image.png
              • 帶有接受者的函數(shù)類型和不帶有接受者的函數(shù)類型轉(zhuǎn)換:
                • 轉(zhuǎn)換方式:前者轉(zhuǎn)換為后者方式:將接受者對象作為第一個參數(shù)傳遞給后者,即后者在前者參數(shù)的基礎(chǔ)上多一個參數(shù),此參數(shù)為接受者對象。


                  函數(shù)類型轉(zhuǎn)換

                  函數(shù)類型的轉(zhuǎn)換2
              • 函數(shù)類型的調(diào)用:
                • 函數(shù)類型的實(shí)現(xiàn)函數(shù)是invoke函數(shù),所以通過變量名的invoke調(diào)用即可以調(diào)用聲明的這個函數(shù)類型。即變量名.invoke(參數(shù))
                • 直接調(diào)用 : 也可以通過 函數(shù)類型變量名(參數(shù)列表) 直接調(diào)用該函數(shù) , 將該變量名稱當(dāng)做函數(shù)名稱來使用,即 變量名(參數(shù))
  3. lambda表達(dá)式:
    • lambda表達(dá)式的語法:{ x : int ,y:Int -> x+y }
      • kotlin中l(wèi)ambda表達(dá)式始終用花括號包圍,注意參數(shù)部分沒有用括號括起來,箭頭可以把實(shí)參列表和lambda的函數(shù)體隔開
      • 其中 箭頭 -> 前的部分是參數(shù),箭頭后面是函數(shù)體
      • 參數(shù) -> 函數(shù)體:多個參數(shù)中間使用,隔斷,參數(shù)的類型若是kotlin能夠自動推斷出來可以不直接指明其類型。
      • lambda表達(dá)式的函數(shù)體可以是單行也可以是多行,最后一行默認(rèn)是lambda表達(dá)式的返回值需要注意的是最后一行返回值的類型必須和lambda表達(dá)式變量聲明的返回值的值類型保持一致,若不一致則會出現(xiàn)異常。
      • 由lambda表達(dá)式的語法可知:lambda表達(dá)式是不能夠直接聲明返回值的類型的,通常是由其函數(shù)體部分的最后一句語句推斷出來的。
    • lambda表達(dá)式類型(變量)完整語法:val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }


      lambda語法

      備注:

      • 常量關(guān)鍵字 常量名稱 : 參數(shù) -> 返回類型 = { lambda表達(dá)式 }
      • 參數(shù)聲明在大括號中,多個參數(shù)使用,隔開,0參數(shù)則()表示,單參數(shù)使用(參數(shù))表示,參數(shù)中的某個參數(shù)也可以是一個參數(shù)類型(lambda表達(dá)式或者匿名函數(shù)等實(shí)例化即可) 參數(shù)可選即kotlin若能通過lambda表達(dá)式推斷出參數(shù)的類型則語法中的參數(shù)類型(大括號)可以省略。
      • lambda若能夠自動推斷出返回值的類型則返回類型(變量聲明的返回值類型)可以省略,但是Unit不能省略,因?yàn)閗otlin是默認(rèn)函數(shù)體的最后一行是返回值所以倘若不需要返回值則必須聲明Unit(此處的聲明是函數(shù)類型的語法聲明所以Unit不能去掉)
      • 由于參數(shù)類型中的參數(shù)類型和返回值類型可以省略所以此時省略后的語法:val sum = { x: Int, y: Int -> x + y }


        lambda表達(dá)式作為變量
      • 針對一個高階函數(shù),倘若高階函數(shù)的最后一個參數(shù)是lambda表達(dá)式,那么此函數(shù)調(diào)用的時候可以將最后一個參數(shù)(lambda表達(dá)式)放到函數(shù)參數(shù)大括號的外面,即:


        尾綴lambda表達(dá)式
      • 倘若lambda表達(dá)式僅僅有一個參數(shù),即其參數(shù)唯一的時候此時lambda表達(dá)式可以不聲明參數(shù)即可以忽略->前面的語法,直接去寫表達(dá)式的函數(shù)體,此時唯一參數(shù)可以使用關(guān)鍵字it標(biāo)識,即:


        it關(guān)鍵字
        • 常規(guī)lambda表達(dá)式是沒有return語句的,最后一句語句就是返回值,返回值類型就是lambda表達(dá)式的返回值類型,如果使用 帶標(biāo)簽限定的 return 語法, 你可以在 Lambda 表達(dá)式內(nèi)明確地返回一個結(jié)果值(帶標(biāo)簽限定的return語法:和標(biāo)簽限定this一致,通過標(biāo)簽標(biāo)明return指向的那個對象,即return@filter表示 該返回值是函數(shù)filter的返回值). 否則, 會隱含地返回 Lambda 表達(dá)式內(nèi)最后一條表達(dá)式的值.


          lambda表達(dá)式返回值
        • 在高階函數(shù)調(diào)用的時候,需傳入的lambda表達(dá)式,如果 Lambda 表達(dá)式的某個參數(shù)未被使用, 你可以用下劃線來代替參數(shù)名:


          lambda表達(dá)式:下劃線
        • Lambda表達(dá)式的解構(gòu):此處不詳細(xì)描述,放到對應(yīng)的解構(gòu)模塊去解析。
  4. 匿名函數(shù):kotlin中函數(shù)的聲明語法中不聲明對應(yīng)的函數(shù)名則被稱為匿名函數(shù):
    • 語法:fun(參數(shù)) :返回值 { 函數(shù)體}
    • 匿名函數(shù)和lambda表達(dá)式的區(qū)別:
      • lambda表達(dá)式語法:{參數(shù)-> 函數(shù)體},由其語法可了解到 lambda表達(dá)式是沒有返回值返回的,通常根據(jù)其函數(shù)體的最后一句語句判斷出返回值類型,若想直接聲明返回值的類型則可以通過匿名函數(shù)來聲明。
      • lambda表達(dá)式是沒有return語句的,所以lambda表達(dá)式是不能夠直接返回的,若返回需要從lambda表達(dá)式所屬的函數(shù)中返回,但是匿名函數(shù)則不然,匿名函數(shù)則存在return語句可以在自己的函數(shù)體執(zhí)行完畢后直接返回。
    • 和函數(shù)相比,匿名函數(shù)的區(qū)別是省略了函數(shù)名稱,其函數(shù)體可以是單行也可以是多行,若單行可以省略掉{},此時成為匿名函數(shù)表達(dá)式(使用=替換掉原有的{}),即:


      匿名函數(shù)表達(dá)式
    • 匿名函數(shù)的參數(shù)類型和返回值類型若能夠自動推斷出來則可以省略掉其類型聲明,若函數(shù)體是多行且沒有返回值的時候則必須聲明Unit,和java一致,沒有返回值則必須聲明void一致。
    • 匿名函數(shù)作為高階函數(shù)的最后一個參數(shù)的時候,在調(diào)用的時候匿名函數(shù)不能放到高階函數(shù)的大括號外部(參數(shù)),能夠放到其外部的僅有l(wèi)ambda表達(dá)式。
  5. 閉包:
    • 閉包:在java中線程或者監(jiān)聽方法中,若要是想訪問外部函數(shù)中聲明的局部變量則必須將其定義為final,且在其內(nèi)部不能夠修改局部變量(final的局部變量不被修改),對于此情況 kotlin提供了閉包的概念,在閉包中可以直接訪問外部函數(shù)中的局部屬性,對于var聲明的外部屬性還可以修改屬性。
    • 閉包的原理:針對閉包由其編譯后的JAVA文件可知:將其外部屬性編譯成為一個final的局部對象變量(比如局部變量是int 編譯后變量名對應(yīng)的是Integer對象)且這個局部對象變量還聲明了一個屬性其屬性對應(yīng)的值是先前局部變量的值,即int i = 5編譯后是:Integer i = new Integer(),i.element = 5所以在閉包中不僅可以訪問這個屬性還可以修改這個屬性:


      kotlin閉包

      kotlin閉包編譯后的代碼
    • lambda表達(dá)式,匿名函數(shù)的函數(shù)體都可以看做其閉包,即在其函數(shù)體內(nèi)都可以訪問外部函數(shù)聲明的局部屬性甚至可以直接修改其外部屬性。


      閉包

參考文章:
kotlin:函數(shù)類型
kotlin:常用的高階函數(shù)
kotlin:list的常見操作函數(shù)
kotlin:lambda表達(dá)式
kotlin:lambda表達(dá)式
kotlin:閉包原理
kotlin:閉包

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容