Swift Closure | Swift 基礎篇 Closure(閉包)

Hey Apple, What is Closure?

Closures are self-contained blocks of functionality that can be passed around and used in your code.
 — Apple

上面是官方對於 Closure 的解釋,我相信在正常情況下,應該沒人有辦法靠這句話就瞭解它。那到底該怎麼去理解 Closure 呢?其實說穿了,他就是 Function 的改良產物,先來看看改良後長什麼樣子


Closure 語法

by Apple

從官方的提供Closure Syntax,可以發現 Closure 比起 Function 真的簡潔很多,那這兩者到底差在哪裡呢?


Function V.S. Closure

func normal_Func() { }              // Function
var closure_Func = { () -> () in } // Closure

Function

  • 有 Function 名稱
  • 需要加上 func keyword

Closure

  • 沒有 Function 名稱
  • 沒有 func keyword
  • 要加上 in keyword

經過比較應該對 Closure 有初步的認識了,接下來我們透過實際的 Code 教大家該怎麼使用


Example 1 — 把 Function 化成 Closure 形式

func multipy(op1: Double,op2: Double) -> Double {  
return op1 * op2
}
  1. {} 移除
func multipy(op1: Double,op2: Double) -> Double 
return op1 * op2

2. 在 argument 與 function body 中間加上 in keyword

func multipy(op1: Double,op2: Double) -> Double in
return op1 * op2

3. 把 func keyword 與 function 名稱移除

(op1: Double,op2: Double) -> Double in
return op1 * op2

4. 把 {} 加在頭尾之後,並用 var 把 Closure 存起來

var multipy = { (op1: Double,op2: Double) -> Double in
return op1 * op2 }

multipy(10.5, 11.5)

以上就是把 function 化成 Closure 的完整方法,呼叫方法與 function 一樣,但是表達式整個簡潔許多。但是,這來不是最省略的,接下來我將用另外一段 Code 來示範


Example 2 — Closure 再化減

var multipy = { (op1: Double,op2: Double) -> Double in
return op1 * op2 }

private enum Operation {
case binaryOperation((Double, Double) -> Double)
...
}

private var operations: Dictionary<String, Operation> = [
"×" : Operation.binaryOperation(multipy),
"÷" : Operation.binaryOperation({ (op1, op2) -> Double
in return op1 / op2 }),
"-" : Operation.binaryOperation({ (op1, op2) in
op1 - op2 }),
"+" : Operation.binaryOperation({ $0 + $1 }),
...
]

上面是一個計算機 App 的一段 Code ,目的是想要做出一個 Dictionary ,當傳入 + - × ÷ 時,能夠把參數作出對應的運算,然而如果每次要寫入一個新的運算子,就要創一個新的 function 實在太冗長。因此透過 Closure的方式改成上面 ÷ - + 的做法,就變得簡單易讀。

5. 因為 Swift 可以自動判斷上下文的型別,所以 Double 可以省略

"×" : Operation.binaryOperation( { (op1, op2) -> Double 
in return op1 * op2 })

6. 既然有了 in ,那 return 也可以省略了

"×" : Operation.binaryOperation({ (op1, op2) -> Double 
in op1 * op2 })

7. 參數名稱也可以縮寫,第一個參數為 $0 ,第二個參數則為 $1 ,以此類推,而這樣的寫法同時可以省略 in 關鍵字

"×" : Operation.binaryOperation({ $0 * $1 })

這個看似很難利用的 Closure ,經過實作,不難發現其實它對於 Coding 的幫助可不小,像是 present func 這類有先後順序需求的 func ,也可以透過它來辦到,同時又能讓程式可讀性提高,對於追求優雅代碼強迫症的人一定會愛上這個功能。

ref.