轉向Kotlin——高階函數與Lambda表達式

在調用高階函數時使用Lambda表達式,可以使調用語法更加簡潔,不過要想使用這種調用方式,就需要深入瞭解Lambda表達式的用法。

高階函數

高階函數是一種特殊的函數:它接受函數作爲參數,或者返回一個函數。

先看一個例子:

    fun progress(param: (name: String) -> String) {
        var result = param("hello ")
        Log.e("jia", "" + result)
    }

progress就是一個高階函數,它接收一個函數作爲自己的參數,聲明形參名爲param。而且這個參數傳入一個String類型的name,返回一個String值。在progress函數體中可以使用該函數。

看下如何使用:

fun normalFun(name: String): String {
    return name + "北京"
}

progress(::normalFun)

將函數作爲參數值傳入高階函數,需要再函數名前加兩個冒號(::)作爲標記。當然也可以採用Lambda表達式,如下:

progress({ name -> name + "上海" })

Lambda表達式和匿名函數

Lambda表達式,或者稱爲匿名函數,是一種“函數字面值”,也就是一個沒有聲明的函數,但是可以作爲表達式傳遞出去。

progress({ name -> name + "上海" })

progress是一個高階函數,它接收一個函數作爲參數。參數是一個表達式,本身又是一個函數,也就是說,它是一個函數字面量。

函數類型

對於接受另一個函數作爲自己參數的函數,我們必須針對這個參數指定一個函數類型,例如上方提到的progress函數,參數param的類型是 (name: String) -> String 。在函數progress內部,param作爲一個函數使用,並傳遞給param一個String參數。

Lambda表達式語法

Lambda表達式的完整語法形式,也就是函數類型的字面值。

var sum1 = { x: Int, y: Int -> { x + y } }

Lambda表達式包含在大括號內,在完整的語法形式中,參數聲明在小括號內,參數類型的聲明可選,函數體在“->”符號之後。如果Lambda表達式自動推斷的返回值類型不是Unit,那麼在Lambda表達式函數體中,最後一條(或者是唯一一條)表達式會被當做整個Lambda表達式的返回值。

如果把可以去掉的部分全部省略,可以寫成這樣:

var sum2: (Int, Int) -> Int = { x, y -> x + y }

匿名函數

上面講到的Lambda表達式語法,還有一點沒有說明,就是可以指定函數返回值類型。大多數情況下,不需要指定函數類型,因爲可以自動推斷出。但是,需要明確指定返回值類型,就可以選擇另一種語法——匿名函數。

fun(item) = item > 0

匿名函數看起來和通常的函數聲明很相似,區別在於省略了函數名。函數體可以是一條表達式,也可以是多條語句。

調用例如:

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

閉包

Lambda表達式、匿名函數可以訪問它的閉包,也就是定義在外層範圍中的變量。與Java不同,閉包中捕獲的變量是可以修改的,而在Java中必須用final聲明。

 var sun = 0
        ints.filter(fun(item) = item > 0).forEach {
            sun += it
        }

總結

高階函數和Lambda表達式聽起來似乎很“高端”,其實它們在使用上並沒有多麼複雜,尤其是Lambda表達式,許多高級語言都支持。慢慢熟悉吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章