Swift 的 Function (函式) 介紹

如果有一個人,說他在寫程式從沒用過函式,那他一定不是寫程式的傢伙。函式無論在那個程式語言,都是一定會用到的手法,在 Swift 中也必然!而在 Swift 中我們可以輕鬆使用函式,接下來在這一篇,將介紹 Swift 的函式如何使用!

 

  1. func 參數名稱(參數名1: 資料型別1, 參數名2: 資料型別2) -> 回傳型態 {
  2.     //函式內容
  3.     return 返回值
  4. }

舉例來說,我們可以將函式寫成下列。

  1. func greet(person: String) -> String {
  2.     let greeting = "Hello, " + person + "!"
  3.     return greeting
  4. }

 

接下來,我們再用「函式名稱(參數名1: 值1, 參數名2: 值2)」的方式來呼叫函式。

  1. print(greet(person: "Anna"))
  2. // Prints "Hello, Anna!"
  3. print(greet(person: "Brian"))
  4. // Prints "Hello, Brian!"

 

以上列例子來說,可能藏有一個風險,就是我們的「參數名稱」被猜到啦,也因此 Swift 將函式再改良,可以分成內外不同的參數名稱。

  1. func 參數名稱(外部參數名1 內部參數名1: 資料型別1, 外部參數名2 內部參數名2: 資料型別2) -> 回傳型態 {
  2.     //函式內容
  3.     return 返回值
  4. }

 

舉例來說,我們可以將上例改成以下這樣,這樣一來,person 就變外部參數名,name 才是函式可以使用的變數名稱。

  1. func greet(person name: String) -> String {
  2.     let greeting = "Hello, " + name + "!"
  3.     return greeting
  4. }
  5.  
  6. print(greet(person: "Anna"))
  7. // Prints "Hello, Anna!"
  8. print(greet(person: "Brian"))
  9. // Prints "Hello, Brian!"

 

但如果我們每次都要打外部參數名稱,其實也變討人厭的,也不符合 Swift 懶人精簡的精神,所以我們可以用 _  來取代外部參數名稱,這樣一來我們呼叫函式時,就不用打外部參數名啦!

  1. func greet(_ name: String) -> String {
  2.     let greeting = "Hello, " + name + "!"
  3.     return greeting
  4. }
  5.  
  6. print(greet(person: "Anna"))
  7. // Prints "Hello, Anna!"
  8. print(greet(person: "Brian"))
  9. // Prints "Hello, Brian!"

 

如果我們的函式不需要任何參數呢?很簡單,只要將 () 中全部留空就好啦!

  1. func sayHelloWorld() -> String {
  2.     return "hello, world"
  3. }
  4. print(sayHelloWorld())
  5. // Prints "hello, world"

 

另一個情況,我們的函式不必回傳任何值,這時只要將「回傳型態改為()」就可以了。

  1. func greet(_ name: String) -> () {
  2.     let greeting = "Hello, " + name + "!"
  3.     print(greeting)
  4. }
  5.  
  6. greet("Anna")
  7. // Prints "Hello, Anna!"
  8. greet("Brian")
  9. // Prints "Hello, Brian!"

 

Swift 追求精簡,當回傳的資料型別為空時,甚至連「-> ()」都不用寫。

  1. func greet(_ name: String) {
  2.     let greeting = "Hello, " + name + "!"
  3.     print(greeting)
  4. }
  5.  
  6. greet("Anna")
  7. // Prints "Hello, Anna!"
  8. greet("Brian")
  9. // Prints "Hello, Brian!"

 

函式中一次傳多個參數的範例,在這個範例中,我們定義了兩個相同的函式名稱 greet,但因為參數個數不同,所以 Swift 會將他列為不同的函式,這也就是我們常聽到的多載 (Overloading)

  1. func greetAgain(person name: String) -> String {
  2.     let greeting = "Hello, " + name + " Again!"
  3.     return greeting
  4. }
  5.  
  6. func greet(person name: String) -> String {
  7.     let greeting = "Hello, " + name + "!"
  8.     return greeting
  9. }
  10.  
  11. func greet(person: String, alreadyGreeted: Bool) -> String {
  12.     if alreadyGreeted {
  13.         return greetAgain(person: person)
  14.     } else {
  15.         return greet(person: person)
  16.     }
  17. }
  18. print(greet(person: "Tim", alreadyGreeted: true))
  19. // Prints "Hello again, Tim!"

 

結合了剛剛所說的,我們可以用 _  來取代外部參數名稱,所以可以寫成更精簡。

  1. func greetAgain(_ name: String) -> String {
  2.     let greeting = "Hello, " + name + " Again!"
  3.     return greeting
  4. }
  5.  
  6. func greet(_ name: String) -> String {
  7.     let greeting = "Hello, " + name + "!"
  8.     return greeting
  9. }
  10.  
  11. func greet(_ person: String, _ alreadyGreeted: Bool) -> String {
  12.     if alreadyGreeted {
  13.         return greetAgain(person)
  14.     } else {
  15.         return greet(person)
  16.     }
  17. }
  18. print(greet("Tim", true))
  19. // Prints "Hello again, Tim!"

 

Swift 函式也可以給定預設值,當我們沒有傳值進去時,就會以預設值代替,舉例如下。

  1. func greet(_ name: String = "海芋") -> String {
  2.     let greeting = "Hello, " + name + "!"
  3.     return greeting
  4. }
  5.  
  6. print(greet("Tim"))
  7. // Prints "Hello again, Tim!"
  8. print(greet())
  9. // Prints "Hello again, 海芋!"

 

Swift 中還有巢狀函式 (Nested Functions),在函式裡面可以在建立函式,巢狀內部的函式可以只在巢狀函式中使用,也可以讓外部使用,以下是一個範例。

  1. func chooseStepFunction(backward: Bool) -> (Int) -> Int
  2. {
  3.     func stepForward(input: Int) -> Int
  4.     {
  5.         return input + 1
  6.  
  7.     }
  8.     func stepBackward(input: Int) -> Int
  9.     {
  10.         return input - 1
  11.  
  12.     }
  13.     return backward ? stepBackward : stepForward
  14. }
  15.  
  16. var currentValue = -4
  17. let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
  18. // moveNearerToZero now refers to the nested stepForward() function
  19. while currentValue != 0 {
  20.     print("\(currentValue)... ")
  21.     currentValue = moveNearerToZero(currentValue)
  22. }
  23. print("zero!")
  24. // -4...
  25. // -3...
  26. // -2...
  27. // -1...
  28. // zero!

 

在此範例中,因為 currentValue > 0 不成立,所以會執行 chooseStepFunction(false),這時 moveNearerToZero 就指向了 stepForward 函式了喔!

以上是函式的基本使用方式,如果有問題或是將來有用到更高階的手法,再請留言讓我知道,我會再補充上去的喔!