iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 12
0
Software Development

Swift 菜鳥的30天系列 第 12

Day-12 Swift 語法(8) - Closures

閉包 Closures

閉包是功能獨立的區塊,他可以在你的程式碼中被傳遞及使用,閉包能夠捕獲和儲存定義上下文中任何常數與變數的引用,這被稱為所謂的閉合包裹那些常數及變數,也就是閉包,Swift 能夠為你處理所有關於捕獲的內存管理的操作。

在 functions 中我們有提到全局函數(Global Functions)以及內嵌函數(Nested Functions),這兩者實際上也是一種特別的封包。

  • Global Functions:是一個有名字,但是不會捕獲值的閉包。
  • Nested Functinos:是一個有名字,且能捕獲封閉函數中的值。
  • Closure expressions:閉包表達式,是以輕量級語法(lightweight syntax)編寫的沒有名字閉包,他可以捕獲上下文中的變數以及常數。

Swift的閉包表達式有一個乾淨、簡潔的風格,透過優化能夠在常見的情況下提供簡潔不複雜的語法,他常見的優化包含:

  1. 利用上下文判斷形式參數和返回值的類型
  2. 可以隱式返回來自單表達式的閉包
  3. 簡短的參數名稱
  4. 尾隨閉包語法

閉包表達式 Closure Expressions

閉包表達式可以在簡短行數中就能寫完閉包的語法。閉包表達式為了縮減程式碼行數又不失清楚易讀的特性而提供了一系列的語法優化。

Sorted 方法

使用 sorted 方法後,它會根據你提供的排序閉包將已知類型的數組的值進行排序。一旦它排序完成,會返回與原數組類型大小完全相同的一個新數組,該數組的元素是已經是排序過後的的。原數組不會被這個方法影響。默認下的sorted的功能就是將數組內由小至大排序,字母則是由前到後,如下圖所示:
https://ithelp.ithome.com.tw/upload/images/20171231/20107701BPX3Cga1mg.png

當然我們也可以在 sorted()的括號中加上 (by: )的條件,簡單來說就是將數組中類型相同的兩個值互相比較,讓他可以返回一個 Bool 值來判斷他們的第兩個值的前後順序,如果我們想要讓數組由大到小排序,我們可以定義一個function,並使用 sorted(by:) 指定相同類型的 function。
https://ithelp.ithome.com.tw/upload/images/20171231/20107701g8WCWVPCO8.png

閉包表達式語法

閉包表達式語法能夠使用常數形式參數、變數形式參數和輸入輸出形式參數,但不能提供默認值。可變形式參數也能使用,但需要在形式參數列表的最後面使用。元組也可被用來作為形式參數和返回類型。

我們使用表達式語法來撰寫上面範例的方式 backNum 的 function ,簡短到一行即可撰寫:
https://ithelp.ithome.com.tw/upload/images/20171231/20107701VmUAkVByGv.png

我們一樣使用相同類型的方式 (Int, Int ) -> Bool ,而這邊我們不是去建立一個 functions 而是把這些形式參數類型和返回類型都寫在花括號 {} 中,我們稱為這為行內閉包,最後閉包的函數整體部分由關鍵字 in 導入,表示閉包的形式參數類型和返回類型定義已經完成,並且閉包的函數即將開始。

從語境中判斷類型

因排序閉包為實際參數來傳遞給函數,故 Swift 可以判斷它的形式參數類型和返回類型。例如我們在上面的方法 sorted(by:) 期望的形式參數類型為(Int,Int) -> Bool ,意味著我們也不需特別輸入他的類型,因為所有的類型都已被推斷出來,因此我們的程式碼會變為:

https://ithelp.ithome.com.tw/upload/images/20171231/20107701IArctlZMvb.png

從單表達式閉包隱式返回

單表達式閉包能夠通過刪掉 return 關鍵字來隱式返回表達式的結果,用前面舉例的範例為下
https://ithelp.ithome.com.tw/upload/images/20171231/20107701K5v2OkcwOu.png

這裡,因為 sorted 方法的參數的函數類型明確地表明要閉包要回傳一個 Bool 值,因為閉包的主體包含一個返回Bool 值的單個表達式(a > b),因此 return 關鍵字能被省略。

簡寫的實際參數名

Swift 自動對行內閉包提供簡寫實際參數名,你可以透過 $0 , $1 ,$2 等名字來引用閉包的實際參數值,$0 為第一個參數,$1為第二個參數,以此類推。如果在閉包表達式中使用這些簡寫參數名稱,那麼你可以在閉包的實際參數列表中忽略對其的定義,並且簡寫實際參數名的數字和類型將會從期望的函數類型中推斷出來。 in 關鍵字也能被省略,因為閉包表達式完全由它的函數體組成:

https://ithelp.ithome.com.tw/upload/images/20171231/20107701zbcLLX1dCu.png

運算符函數

終於到最後一個版本了,Swift的 String 定義了關於大於符號的特定字符串實現,讓其作為一個有兩個 String 類型形式參數的函數並返回一個 Bool 類型的值。這正好與sorted 參數所需的函數相匹配。因此,你能簡單的使用 sorted(by: >) 來實現上述的例子:
https://ithelp.ithome.com.tw/upload/images/20171231/20107701JO8STFct49.png



上一篇
Day-11 Swift 語法(7) - Functions 類型
下一篇
Day-13 Swift 語法(9) - 不同的 Closures 方式
系列文
Swift 菜鳥的30天30

1 則留言

0
陳董 Don
iT邦新手 5 級 ‧ 2017-12-31 20:50:13

哇噻哇噻哇噻哇噻哇噻哇噻哇噻哇噻~~~

我要留言

立即登入留言