函式(Function)是用來完成特定事情的獨立程式碼區塊,而函式(Function)最重要的功能,就是可以簡化程式碼,因為相同的程式,不用寫在不同地方,只需要寫一份,然後需要的地方就可以直接使用,降低了程式維護上的困擾,也簡化了程式並增加可讀性。因此不論在哪種程式語言,最重要的功能之中一定有函式(Function),所以每一個函式(Function)都會有一個合適的名字,用來標示函式(Function)是要做什麼功能的,通常函式(Function)取名的規則,是要讓開發者只看名稱就大約能知道這函式(Function)的功能,至於規範原則上與變數的命名規範一樣,使用小駝峰的方式(Lower Camel Case)命名。
先來說一下,一些有關函式(Function)的基本說法,一般在說函示的時候,會用英文function表示函式,因此之後的說明也會直接使用function來說明,通常傳入function的值,稱為「參數」(parameters),當function結束時,傳出function的值,稱為「回傳值」(return value),當要使用function的時候,也就是function需要被執行時,一般稱為「呼叫」(call)或是「調用」,有一點要注意,在呼叫function之前,一定要先定義funciton,不然無法呼叫。
【沒有傳入參數的function】
首先來說一個最簡單的沒有傳入參數的function用法,基本用法如下:
『func + function名稱 + ( ) + { 程式碼 }』
首先說到如何定義一個function,其實就是function的縮寫func,接下來就是function的名稱與(),之後將這function要執行的程式放在大括號{},這就是最基本的一個沒有傳入參數與回傳值得function。那如何呼叫使用呢?基本用法如下:
『function 名稱 + ( )』
『範例說明』
3 - 5 : 定義一個叫做printMessage的function,這function並沒有傳入參數,這function主要是印出”Swift 5 is a great language.”。
7 : 呼叫printMessage的function,所以此時程式會執行第三行叫printMessage的function,所以會印出”Swift 5 is a great language.”。
【有傳入參數的function】
再來說如果有傳入參數的function用法,基本用法如下:
『func + function名稱 + (參數名稱:參數型別) + { 程式碼 }』
傳入參數的目的,主要是提供給function內的程式使用,讓function可以依據參數的不同做不同的處理,例如有一個function是1加到100,如果還需要1加到200,沒有傳入參數的話,只能寫成兩個function,如果有傳入參數的話,只要將傳入的參數設為邊界,這樣就只要一個function,就可以完成1到任意數的加總。然而參數並沒有限定數量,所以要傳入兩個還是三個都可以,兩個參數之間使用逗號(,)相隔開就可以。參數的宣告方式與常數的宣告很像,宣告傳入參數的方法如下:
『參數名稱 + :+ 參數型別』
那如何呼叫使用呢?基本用法如下:
『function 名稱 + (參數名稱 + :+ 參數值)』
『範例說明』
3 - 5 : 定義一個叫做printMessage的function,這function有一個傳入型別為Int的參數version,function內的程式主要是印出”Swift XXX is a great language.”,而XXX會隨傳入version而改變。
7 : 呼叫printMessage的function,並傳入參數version,version的值為4,此時程式會執行第三行叫printMessage的function,並將傳入參數帶入,所以會印出”Swift 4 is a great language.”。
8 : 呼叫printMessage的function,並傳入參數version,version的值為5,此時程式會執行第三行叫printMessage的function,並將傳入參數帶入,所以會印出”Swift 5 is a great language.”。
傳入的參數預設為常數,所以在function內是不能修改的,除非是宣告型別前加上inout,這樣就可以修改參數,一但參數加上了inout時,在傳入參數時必須要加上&,然而&是什麼意思呢?其實就是說呼叫function時,傳進來的是這參數的記憶體位置,因為這是記憶體位置,所以修改這位置上的值之後,不論是function內外讀取時都會是修改後的值。說到這你可能還是不太能理解,那舉一個例子來說明吧,像你到網路上某個網站上去下載圖片,那網站位置就像是記憶體位置一樣,裡面有一張你想下載的圖片,所以更換這網址上的圖片,就會改變你下載的圖片。基本用法如下:
『func + function名稱 + (參數名稱:inout 參數型別) + { 程式碼 }』
那如何呼叫使用呢?基本用法如下:
『function 名稱 + (&參數名稱)』
『範例說明』
3 - 8 : 定義一個叫做swapValue的function,這function有兩個個傳入型別為Int的參數valueOne與valueTwo,在這兩個參數宣告的型別前有inout,所以代表的是傳入的是一個記憶體位置,所以是在function內修改的,function內的程式主要是將valueOne與valueTwo的值互換。
10 : 宣告一個變數numberOne,並給予初始值10。
11 : 宣告一個變數numberTwo,並給予初始值20。
12 : 呼叫swapValue的function,並將numberOne與numberTwo的位置傳進去,所以在前面加上&,因為是傳位置,所以不需要給參數值。
13 : 印出“numberOne = 20 numberTwo = 10”。
Swift的參數有一個比較特別的地方,就是有外部名稱與內部名稱兩種,簡單的說就是定義function時在大括弧{}內用的參數名稱就是內部名稱(parameter name),而呼叫function的小括弧()內用的參數名稱就是外部名稱(argument label),一般來說內部名稱與外部名稱會是一樣,因爲swift預設會自動產生內外同名稱的參數,當有需要不一樣的時候也是可以的,基本用法如下:
『func + function名稱 + (外部名稱 內部參數名稱:參數型別) + { 程式碼 }』
所以在定義function的傳入參數時,在內部名稱前面加上外部名稱就可以,這樣在呼叫function的時候,就可以使用外部名稱。基本用法如下:
『function 名稱 + (外部名稱 + :+ 參數值)』
『範例說明』
3 - 9: 定義一個叫做printMessage的function,這function有一個傳入型別為Int的參數,內部名稱為money,外部名稱為car,在第四行使用if判斷money是否大於等於1000000,如果判斷條件成立回傳”This car is very expensive.”,如條件不成立回傳”This car is very cheap.”。
10 : 呼叫printMessage的function,並傳入外部參數名稱為car,其值為700000,此時程式會執行第三行叫printMessage的function,因為條件不成立,所以會回傳後會印出”This car is very cheap.”。
如果不想要外部參數名,那在定義function的時候,外部名稱使用下底線( _ )來宣告就可以。基本用法如下:
『function 名稱 + (_ + :+ 參數值)』
這樣在呼叫function的時候,就可以直接給值,而不需要外部參數名。基本用法如下:
『function 名稱 + (參數值)』
『範例說明』
3–9: 定義一個叫做printMessage的function,這function有一個傳入型別為Int的參數,內部名稱為money,外部名稱宣告為_,在第四行使用if判斷money是否大於等於1000000,如果判斷條件成立回傳”This car is very expensive.”,如條件不成立回傳”This car is very cheap.”。
10 : 呼叫printMessage的function,因為外部名稱宣告為_,所以不需要外部名稱,直接給值為700000,此時程式會執行第三行叫printMessage的function,因為條件不成立,所以會回傳後會印出”This car is very cheap.”。
最後要說一下的是傳入的參數可以有預設參數值(Default Parameter Values),當呼叫時沒有傳入,則在function中該參數會使用預設值。基本用法如下:
『func + function名稱 + (參數名稱:參數型別 = 預設值) + { 程式碼 }』
『範例說明』
3–9: 定義一個叫做printMessage的function,這function有一個傳入型別為Int的參數,內部名稱為money,預設值為700000,在第四行使用if判斷money是否大於等於1000000,如果判斷條件成立回傳”This car is very expensive.”,如條件不成立回傳”This car is very cheap.”。
10 : 呼叫printMessage的function,並未傳入參數,此時程式會執行第三行叫printMessage的function,因為沒有傳入參數,所以參數money使用預設值700000,所以條件不成立,所以會回傳後會印出”This car is very cheap.”。
【有回傳值的function】
再來說如果有回傳值(Return Values)的function用法,基本用法如下:
『func + function名稱 + (參數名稱:參數型別) + -> + 回傳的型別 + { 程式碼 + return 回傳值 }』
當需要function執行完畢後回傳一些需要的資訊,如執行完function是正確還是錯誤或是需要回傳一些數值,然後做下ㄧ個判斷等等…,這時就需要有function有回傳值了。需要回傳的function可以有參數傳入,也可以沒有,這之間並沒有什麼相互關聯,純粹看開發者的需要,那在function中要如何回傳呢?其實就是用return後面加上要回傳的值,必須要注意的是必須與定義時的回傳型別一致,而且一但return就會結束這function,如後面還有其他的程式碼也不會再繼續執行。
『範例說明』
3 - 10: 定義一個叫做printMessage的function,這function有一個傳入型別為Int的參數version,並且當function執行完畢時,會回傳一個字串型別的字串回去,當version為5的時候會回傳”Swift 5 is a great language.”,其他的值則會回傳”Please change the Swift version to 5.”。
11 : 宣告一個型別為String的變數message.”。
12 : 呼叫printMessage的function,並傳入參數version,version的值為4,此時程式會執行第三行叫printMessage的function,並將傳入參數帶入,所以當function執行完,會回傳”Please change the Swift version to 5.”,因此用一個型別為String的變數message來接。
13 : 印出”Please change the Swift version to 5.”。
12 : 呼叫printMessage的function,並傳入參數version,version的值為5,此時程式會執行第三行叫printMessage的function,並將傳入參數帶入,所以當function執行完,會回傳”Swift 5 is a great language.”,因為回傳的是字串型別,所以可以用print直接印出”Swift 5 is a great language.”。
如果function內只有一行程式,那麼return可以省略,只要不止一行程式,就不能省略return。
『範例說明』
3 - 5: 定義一個叫做printMessage的function,這function有一個傳入型別為Int的參數lineNumber,並且當function執行完畢時,會回傳一個字串型別的字串回去,當lineNumber為10的時候會回傳”Just one line code : 10.”,因為只有一行程式,所以可以省略掉return。
6 : 呼叫printMessage(),並傳入lineNumber為10,所以回傳後印出”Just one line code : 10.”。
如果有多個回傳值需要回傳,有幾種方式,將回傳值放入可以容納眾多資料的元組(tuple)、陣列(array)還是字典(dictionary)等等…都可以,目前尚未介紹到這些,之後會有說明,目前只要知道也可以回傳多個值就可以。
最後要注意的就是相同的function名稱是允許的,只要傳入的參數名稱不同或是參數型別不同,還是回傳型別不同,都算是不同的function。如果不太明白可以參考下面的範例一起了解。
『範例說明』
3 - 5: 定義一個叫做printMessage的function,這function有一個傳入型別為Int的參數message,並且當function執行完畢時,會回傳一個字串型別的字串回去。
7 - 9 : 定義一個叫做printMessage的function,這function有一個傳入型別為Int的參數messageName,並且當function執行完畢時,會回傳一個字串型別的字串回去。
11 - 13 : 定義一個叫做printMessage的function,這function有一個傳入型別為String的參數message,並且當function執行完畢時,會回傳一個字串型別的字串回去。
15 - 18 : 定義一個叫做printMessage的function,這function有一個傳入型別為String的參數message,並且當function執行完畢時,會回傳一個整數型別的整數回去。
19 : 宣告一個整數型別的變數returnInt。
20 : 宣告一個字串型別的變數returnString。
21 : 呼叫printMessage(),傳入型別為整數的參數message,傳入值為20,用returnString接回傳的字串。
22 : 印出returnString中所存的回傳字串,印出“printMessage(message: Int(20)-> String.”。
23 : 呼叫printMessage(),傳入型別為整數的messageName,傳入值為10,用returnString接回傳的字串。
24 : 印出returnString中所存的回傳字串,印出“printMessage(messageName: Int(10)-> String.”。
25 : 呼叫printMessage(),傳入型別為字串的message,傳入值為“5””,用returnString接回傳的字串。
26 : 印出returnString中所存的回傳字串,印出“printMessage(message: String(5)-> String.”。
27 : 呼叫printMessage(),傳入型別為字串的message,傳入值為“1””,在程式第16行裡,呼叫print,直接印出”printMessage(message: String(1)-> Int.“,最後結束function後回傳整數0,用returnInt接回傳的整數,在這裡回傳的整數0,並沒有使用。