基本函數 - 介紹
函數是一個,用以執行特殊目的一個程式區塊這是一個swift的基礎函數說明
func functionName(parameters)-> returnType {
// function body
}
舉例來說,有一個做香腸的函數,我們只要把豬肉放進去,裡面怎麼做,因為被函數包起來了,實作細節要進到函數裡詳查,但函數產出的結果,會得到香腸。

func 香腸產生器(放入的肉:豬肉型別)-> 香腸型別 {
// function body
return 1 根香腸
}
當然,一個簡單的函數也可沒有input 也沒有output
func greeting() {
print("Hello World!")
}
如果函數完成了之後,要怎麼樣使用呢?只要在程式的生命週期裡,適當的地方呼叫
greeting()
//或者是
var return = 香腸產生器(5隻豬)
print(return) // 100 根香腸
使用系統內建的函數
其實,print() 就是一個系統內建的函數
print("ABC")
再舉多一個取極大值的例子
import Foundation
var value = max(3, 5)
print(value) //5
在使用系統內建的函數,或是使用別的做好的函數庫,在使用之前,都會有個 import 函數庫的操作。如此,能夠使用已經有的函數庫,就不用自己一再地重覆造輪子了
沒有輪子?自己造一個吧!!!
第一個使用者自行定義的函數
用函數來實作一個加法器
加法器函數範例
func addNumbers(num1: Int, num2: Int) -> Int{
return num1 + num2
}
有一個函數,名字叫做「addNumbers」,有兩個輸入參數,分別為 num1 與 num2,型別為 Int, 回傳值 是一個 Int, 能夠回傳 兩個數相加的值。
讀懂程式,是在學習寫程式之前很重要的一個步驟
呼叫函數
var result = addNumbers(num1: 3, num2: 4)
print(result). //7
其中 num1 與 num2 是具名參數,如果想要少打一點字,可以使用不具名參數
func addNumbers(_ num1: Int, num2: Int) -> Int{
return num1 + num2
}
num1 前多了個 “_”
呼叫函數,就要配合改為
var result = addNumbers(5, num2: 6)
print(result). //11
想要為參數加一個別名,也可以寫成醬子
func sum(of num1: Int,and num2: Int) -> Int{
return num1 + num2
}
num1 前多了個 “of”, num2 前多了個 “and”
呼叫函數,就要配合改為
var result = sum(of :5, and : 6)
print(result). //11
是不是比較容易讀了呢?
函數的多種變化
不定量參數的函數 (Function with variadic parameters)
有時候想要傳很多參數但參數又不是固定幾個的時候,swift 語言提供了一種未限定參數個數的函數,範例如下:
func sum(numbers: Int...) -> Int{
var result = 0
for num in numbers {
result += num
}
return result
}
型別的後面多了 … , 代表著,傳入的參數 numbers, 其實是一個型別為 Int 的 collection,可以讓你傳入 0~很多個參數到函數裡面,而在函數中取值的話,用迴圈把參數裡的值一一取出利用。
呼叫函數的方法為
var rtn = sum(numbers:1,2,3,4,5)
print(rtn)
回傳多個值的函數 (Function with return multiple values)
有時候想要回傳很多值的時候,可以回傳一個 Tuple,範例如下:
func sum(numbers: Int...) -> (String, Int) {
var result = 0
for num in numbers {
result += num
}
return ("經過計算後的結果", result)
}
巢狀函數 (Neste木Function)
函數裡面也可以再放函數,沒問題的,生命週期也僅限於相同的一個 Code Block 裡使用
func 香腸產生器() {
// code
func 調味() {
// code
}
調味()
}
傳址呼叫 Call By Reference
函數的參數中帶有 inout??
func 肉肉加工函數(肉: 豬肉)-> 豬肉 {
//bla bla bla
//肉 = 處理好的肉???
//如果你想把傳進來的肉再次地賦值,會發現不會成功
//因為此時傳進來的"肉" 是以 let 存在的變數
//
let 處理好的肉 = 肉+肉+肉
return 處理好的肉
}
//另一種寫法
func 肉肉加工函數(肉: inout 豬肉) { //這裡多 inout
//肉 就不是 let 型式了, 而是指向記憶體位置的 var
肉 = 處理好的肉
}
//呼叫方式有點不同
var 將要被處理的肉 : 肉
肉肉加工函數(肉: &將要被處理的肉) //多了一個&在變數前面
print(將要被處理的肉) // 其實變成處理好的肉
有關於傳址乎叫 Call ByReference 還是 / 傳值呼叫 Call ByValue
留待下下章 Reference Type / Value Type 時再解釋。
遞迴 Recursion
什麼是遞迴? 原理其實很簡單,就是函數裡的處理過程中,再次呼叫自己的函數。
func recurse() {
... ...
recurse()
... ...
}
recurse()
停不下來?? 對,這就是遞迴的重點,要有跳脫的機制,不然就會陷入無窮迴圈,不斷地呼叫,而造成記憶體堆疊而炸掉程式。
經典範例1
func cumulativeSum(_ number:Int) -> Int {
if number == 1 { //跳脫條件
return 1
}
//不符合條件就往下繼續
return number + cumulativeSum(number - 1)
}
print(cumulativeSum(5))
經典範例2
func fibonacci(_ i:Int) -> Int {
if i <= 2 { return 1 }
return fibonacci(i - 1) + fibonacci(i - 2)
}
print(fibonacci(5))
函數多載(Overloading)
實務經驗中,函數的功能一樣,但有可能輸入的參數的型別不同,那麼,要讓開發者在使用中儘量地不改變開發的習慣時,就會再多寫一個多載函數
func calAge(_ age:Int){
...
}
func calAge(_ age:String){
...
}
//呼叫
calAge(18)
calAge("18")
或者,參數的型別相同,但命名的別稱不同,使用的情境也不同。
func calAge(bank age:Int){
...
}
func calAge(householdAdmin age:int){
...
}
//呼叫
calAge(bank:18)
calAge(householdAdmin:18)
閉包 Closure 也可以算是一種內聯函數(inline function),或是匿名函數的表示方式,但有點篇幅 所以下一章再講
運算子方法(Operator Method)
雖然和函數看起來關係不大,不過也稱得上是隱式的函數的終極簡化版,晚點有機會再說明。
使用函數的好處
- 簡化程式與重複利用
- 增加程式的可讀性
- 每個函數就像是積木一樣,一塊塊排好,就可以做出完整的功能
轉載請註明來源,歡迎對文章中的引用來源進行考證,歡迎指出任何有錯誤或不夠清晰的表達。可以郵件至 [email protected]