1. 閉包
-
一個函數和它所捕獲的變量/常量環境組合起來,稱為閉包
- 一般指定義在函數內部的函數
- 一般它所捕獲的是外層函數的局部變量/常量
typealias fn = (Int) -> Int func getFn() -> fn{ var count = 0 func sum(_ i: Int) -> Int{ count += i return count } return sum } var f1 = getFn() f1(1) f1(1) f1(1) f1(1)結果:
解釋:
閉包能夠使用其外層函數的局部變量,所以函數值能夠增加
本質:
編譯器給sum函數外層getFn函數的count屬性分配了堆空間,所以count變量不會在getFn函數執行完後銷燬,因此sum函數能夠對其進行訪問
分配內存結構: 類似於給class分配的堆空間結構
![image]()
-
可以把閉包想象成一個對象的實例
- 內存在堆空間
- 捕獲的局部變量/常量就是對象的成員
- 組成閉包的函數就是類內部定義的方法
類似與class的形式:
class Closure{ var count = 0 func sum(_ i:Int) -> Int{ count += i return count } } var c1 = Closure() c1.sum(1) c1.sum(1) c1.sum(1)
2. 閉包表達式
- 語法:
{ (參數列表) -> 返回值類型 in 函數體代碼 } - 簡寫:
func exec(v1:Int, v2:Int, fn:(Int, Int) -> Int){ print(fn(v1, v2)) } // 完整寫法: exec(v1:10, v2:20, fn:{ (a1:Int, a2:Int) -> Int in return a1 + a2 }) // 簡寫1 exec(v1:10, v2:20, fn:{ a1, a2 in return a1 + a2 }) // 簡寫2 exec(v1:10, v2:20,fn:{ a1,a2 in a1 + a2 }) // 簡寫3 exec(v1:10, v2:20, fn:{ $0 + $1 }) // 簡寫4 exec(v1:10, v2:20, fn: + ) // 尾隨閉包: 是一個被書寫在函數調用括號外面(後面)的閉包表達式 // 如果一個很長的閉包表達式作為一個函數的 最後一個 實參,使用尾隨閉包可以增強程序的可讀性 exec(v1:10, v2:20){ $0 + $1 } // 如果函數只有一個參數,且類型是函數類型,可以省略括號 func add(fn: (Int,Int) -> Int){ print(fn(1, 2)) } add{ $0 + $1 } // 省略參數 add{ _,_ in 10 } //省略掉參數,固定返回10
