天天看點

kotlin 函數提高篇之高階函數與 lambdakotlin 函數提高篇之高階函數與 lambda

kotlin 函數提高篇之高階函數與 lambda

文章目錄

  • kotlin 函數提高篇之高階函數與 lambda
    • 正文
        • 1. 一個例子看高階函數
        • 2. 函數類型
        • 3. invoke 調用函數
        • 4. 閉包
        • 5. 使用下劃線表示未使用的變量
        • 6. 内聯函數

正文

  1. 高階函數就是将函數作為參數或傳回值的函數。

1. 一個例子看高階函數

//[1] 函數擴充, 給集合擴充一個 myfold 方法, 用作集合的累計器
//比較像政策模式,定義一個政策,實作方實作具體政策
fun <T, R> Collection<T>.myfold(
    initial: R,
    combine: (acc: R, nextElement: T) -> R
): R {
    var accumulator: R = initial
    for (element: T in this) {
        println("myfold ::執行前 $accumulator")
        accumulator = combine(accumulator, element)
        println("myfold :: acc = $accumulator, i = $element")
    }
    return accumulator
}


fun main() {
    val items = listOf(1, 2, 3, 4, 5)

    var myfold = items.myfold(initial = 0,
        // [2] Lambda 表達式就是花括号擴起來的代碼塊
        combine = {
            //[3]? 如果一個 lambda 有參數,前面參數,後面跟 '->', 箭頭後面的都是 lambda 表達式
                acc: Int, nextElement: Int ->
            println("main::acc = $acc, i = $nextElement")
            val result = acc + nextElement
            println("main::result = $result")
            // [4] lambda 表達式最後一個就是傳回值
            result

        })
    println("$myfold")
}
           

2. 函數類型

4個概念記一記

//[1] kotlin 使用類似 (Int) -> String 來聲明函數
val onClick:() -> Unit = {}

//[2] 下面表示接受 A 與 B  兩個參數,并傳回 C 類型值的函數類型
(A, B)-> C
val sum:(Int, Int) -> Int = {x:Int, y:Int -> x + y}

//[3] 帶接受者的函數,如下。
A.(B) -> C

//[4] 挂起函數,有 suspend 修飾符
suspend A.(B) -> C
           

3. invoke 調用函數

//[1] 使用 invode 來進行函數變量的函數調用
val add:(String , String) -> String = {a, b -> a + b}
println(add("s", "s"))
println(add.invoke("s2", "s2"))
           

4. 閉包

  1. kotlin 一個不成文的約定,如果函數最後一個參數是函數,那麼相應參數傳入的 lambda 表達式可以放在圓括号外
  2. 如果該 lambda 表達式是調用唯一參數,那麼圓括号也可以省略
//[1] 是否帶函數參數的函數,有點繞哈
    bibao1(1 ,{b -> 
        1
    })

    //[2] 編譯器會提示,因為最後個參數是函數參數你觸發了閉包條件,可以使用閉包
    bibao1(1) { b ->
        1
    }

    //[3] 這個樣子,就觸發不了閉包條件
    bibao2(1 ,{b ->
        1
    }, 2)

    //[4] 因為沒使用參數,再次提示隐藏參數
    bibao1(1) {
        1
    }
           

5. 使用下劃線表示未使用的變量

//[1] 第一個參數未使用,但是第二個使用了,導緻不能省略,但是可以略寫啊
map.forEach { _, value -> println("$value!") }
           

6. 内聯函數

  1. 使用高階函數會有運作時的效率損失,因為對函數對象的記憶體配置設定和虛拟調用會引入時間開銷
  2. inline 修飾符會影響函數本身和傳給它的 lambda 表達式,将所有這些都内聯到調用處