閉包(closure)大概是我在函式這個單元過後,卡的稍微久一點的一個關卡,主要是弄不清楚閉包到底跟函式有什麼區別,但時間久了之後,可能就會稍微忘掉閉包的一些小基礎,所以閉包這個單元會大致上分成二個部分:
本篇會先描述第一種。
而閉包的參數傳入型別與傳出值型別設定,都依靠著in這個標記來讀取前面的參數功能,清楚表明參數的傳入值與傳出值是什麼。
其實邏輯都跟函式有點相近,但閉包的語法,其實有更大的重點在於傳入值型別與傳出值型別的描述,像你可能會看到的String->() or (String)->String,這個東西的重要性是閉包在運作的過程裡,最核心的一環。
所以,我們大致上知道影響閉包的運作,有很大一部分是in標記之前的傳入值型別與傳出值型別描述,因此,上述提到的有兩種:
而現在要描述的第三種比較特別,是閉包作為參數(closures as parameter):
如上面程式碼寫的,先把一個閉包的內容定義好,傳入型別、傳出型別也對應好要傳入的函式,然後,再把定義好的函式,將閉包的內容丟進去函式的呼叫裡面。
當然,閉包跟函式的組合可以很複雜,複雜到想要哭,不過,這邊就簡單的介紹,往後如果有更多的案例,可以繼續在後面的文章繼續的看到。
綜合上述,閉包和函式很像,但是閉包可以有更多功用,像是閉包可以作為參數這點,傳入函式就非常的好用,甚至可以在未來寫程式的時候創造複雜性。
尾隨閉包這件事情很有趣,它是一個極度省略的概念(如果就表象上看起來啦),假若今天有個函式長這樣:
閉包在裡面叫做action,傳入型別為()->Void
一般我們在呼叫這個函式的時候,照理來說應該長得像下面這個樣子,所有的東西都會好好地顯示在畫面上:
但尾隨閉包不是這樣,它會把閉包的部分省略掉,也就是說,在下面這個尾隨閉包的案例中,閉包的部分因為型別是()->Void,所以可以這樣做:
工程師真是一種奇怪的東西,東省西省,不過確實如果仔細讀意思的話,我們可以很清楚的知道,省略的東西就是所謂閉包的部分。
不過,假如今天我們只有一個閉包在函式裡面的話,我們在呼叫函數的時候,假若裡面什麼東西都沒有要傳進去的參數或值,可以把函式的括號部分省略,變成下面這個樣子:
總而言之,尾隨閉包幾乎可以說是一個省略東西的狀態,但卻也讓呼叫的時候,更清楚的知道,尾隨在呼叫函式後的內容,就是所謂的閉包的部分了。
假如我們新增一個函式如下,但它有個「傳入型別跟傳出型別都是String」的閉包叫action:
這時候,我們開始呼叫閉包,我們可以很清楚的知道,呼叫的時候,func travel( )的func、( )少掉了,func本來就可以省略,而( )則因為裡面沒有其他重要參數,所以也省掉了,後面就是一個引數的內容,藉由in隔開了(place:String)->String
但因為在宣告函式的時候,就已經宣告了型別的傳入與傳出,所以Swift會認定呼叫閉包的時候傳入、傳出型別都是String,所以可以在步驟一中省略引數型別,
在步驟二中,省略傳出型別:
步驟三中,整個都省略,因為一定會回傳String這個這個值,Swift知道,所以這回連return也可以省略,畢竟它是一定會回傳的東西,
而在return中的place的位置,可以藉由$0取代,這個叫做參數名稱縮寫,然後我記得如果有多少個參數,就可以依序以$0、$1、$2……等等的命名。
不過要記得一件事情:這種替代是方便開發者做事情,而不要看到看起來很簡便,就一直用,如果參數沒有幾個的話,這樣用是很方便的,但假若多起來,可能就不是那麼好管理的一件事情了。
鐵人賽