1. 程式人生 > 其它 >swift 閉包本質,閉包表示式,尾隨閉包

swift 閉包本質,閉包表示式,尾隨閉包

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分配的堆空間結構

    • 可以把閉包想象成一個物件的例項

      • 記憶體在堆空間
      • 捕獲的區域性變數/常量就是物件的成員
      • 組成閉包的函式就是類內部定義的方法
        類似與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