第一篇有提到 Kotlin 的其中一個特點就是 Functional Programming,今天的 lambdas 也會圍繞在這個特點,在進入 lambdas 之前會先聊聊 Higher-order functions 也是構成 Functional Programming 的其中一個要點,以下如有解釋不清或是描述錯誤的地方還請大家多多指教:
我們先來複習一下構成 Functional Programming 的幾個要點:
所以在使用這個設計方法,我們會用到大量的 function types,lambda 表示式提供了特殊的語言結構,而在 Java8 開始也有 lambda 表示式,簡單來說 lambda 表示式簡化了 function 呈現的形式。
接下來會依序解釋 function types
, Higher-order functions
, lambdas
如何呈現:
Function type 以字面上的意思做解釋,就是參數類型以 function 的形式呈現,一般我們常見的類型就是 primitive type(原始型別)或是 object type(物件型別):
val a: Int = 0 // primitive type
val b: Person = Person() // object type
val onClick: () -> Unit = ... // function type
那我們來看看他的結構吧 () → Unit
左邊是輸入,右邊是輸出,還原成原本的樣子應該就會很清楚了:
fun onClick() : Unit {}
// 如果沒有命名呢? 我們稱之為匿名函數
fun () : Unit {}
如果說我們希望輸入是有值的那該怎麼寫呢?
// non-null
fun count(a: Int, b: Int) : Int {
return a + b
}
val count: (Int, Int) -> Int = ...
// nullable
fun count(a: Int, b: Int) : Int? {
return a + b
}
val count: ((Int, Int) -> Int)? = ...
這邊也可以透過 type alias 幫 function type 取名字,就像:
typealias ClickHandler = (Button, ClickEvent) -> Unit
val onClick: ClickHandler = ...
將函數類型 (Function type) 作為參數或返回值,以上一篇提到的 scope function 就是一個高階函數的案例:
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
我們可以看到 apply function 裡面的參數就是 Function type。
lambda 表示式跟匿名函式都是 function literals,function literals 是沒有明顯的定義與宣告以表達式的方式呈現:
// a Higher-order functions
fun View.visibleElseGone(condition: () -> Boolean) {
visibility = if (condition()) View.VISIBLE else View.GONE
}
val a = 12
// 當我們要使用 visibleElseGone function, 參數以 lambda 表示式的方式帶入
button.visibleElseGone({ a != 0 })
// 這時候 IDE 會提示說 Lambda argument should be moved out of parentheses
button.visibleElseGone { a != 0 }
舉例一個 Kotlin 當中使用 lambda 表示式最經典的案例:
button.setOnClickListener {
// do something
}
// 還原最初的寫法
button.setOnClickListener (object : View.OnClickListener {
override fun onClick(p0: View?) {
TODO("Not yet implemented")
}
})
我們也可以看到 IDE 上的 hint 顯示的 function type: