Swift 函數

前言

  • Swift 中函數是用來完成特定任務的獨立代碼塊。swift

    • 本節所講的函數概念是全局的,不隸屬於某一個數據結構。
    • 沒有 「擁有者」 的函數的做用域是全局的,除非重載,不然不可能定義兩個如出一轍的函數。
    • 在 Swift 語言中沒有主函數。
  • 方法是擁有歸屬關係的函數。數組

    • 方法的 「擁有者」 多是類,也多是結構體等。
    • 方法的 「擁有者」 爲方法提供了命名空間,因此在不一樣的類或者結構體中能夠定義徹底相同的方法。

一、函數的定義

  • 函數定義須要關鍵字 func,其通常格式爲數據結構

    func 函數名 (參數名1: 參數類型, 參數名2: 參數類型, ...) -> 函數返回類型 {
    
        函數體 .....
    
        return 返回值
    }
  • 參數app

    • 在函數定義中,咱們使用的參數叫形式參數,在調用時傳入的參數是實際參數。
    • 參數名後面用冒號相連的是參數類型,在定義函數時,須要明確參數類型。
    • 你能夠指定多個參數,參數間用 , 分割。
  • 返回類型函數

    • 返回值類型使用組合符號 -> 來指示。
    • 若是不須要返回值能夠寫成 -> Void(注意 V 要大寫),或者直接省略 -> 語句。
    • 沒有定義返回類型的函數默認會返回 Void
    • 若是 -> 後面是 Void,則函數體中不須要寫 return 語句。
  • 函數調用編碼

    • 函數調用時只要傳入的參數與函數定義中的參數類型相同便可。
    • 在 Swift 3.0 以前調用函數時,函數的首個參數名是自動隱藏的。
    • 在 Swift 3.0 及以後調用函數時,函數的全部參數是同等地位的,首個參數再也不默認隱藏。

二、函數類型

  • Swift 中函數自己也是一種類型,函數類型一般由函數的形參類型和返回值類型組成。設計

    • 例如,函數code

      func addString(s1: string, s2: string, s2: string) -> String { }
      • 的 函數類型 是排序

        (String, String, String) -> String
    • 若是一個函數沒有形參或返回值,那麼這個函數的類型是 () -> ()element

  • 能夠像使用 Swift 語言中其餘類型同樣使用函數類型。

    • 例如能夠定義一個函數常量或函數變量,並像通常數據類型指定初始值同樣爲他指定一個對應的函數。與其餘類型同樣,當你給函數賦一個變量或者常量時,你可讓 Swift 語言去推斷函數的類型。

      func addString(s1: string, s2: string, s2: string) -> String { }
      
      // 指定函數類型
      var addSome:(String, String, String) -> String = addString
      
      // 推斷函數類型
      let addSome = addString
    • 你也能夠將函數做爲參數傳遞給其餘函數,或者將函數類型看成返回類型。

      func plus(a: Int, b: Int) -> Int {
          return a + b
      }
      
      func mult(a: Int, b: Int) -> Int {
          return a * b
      }
      
      func someFunction(func: (Int, Int) -> Int, a: Int, b: Int) {
          let result = paraFunc(a, b)
          print("The result is \(result)")
      }
      someFunction(paraFunc: plus, a: 3, b: 4)     // The result is 7
      someFunction(paraFunc: mult, a: 3, b: 4)     // The result is 12

三、函數參數

  • 在 Swift 語言中,函數的形參和返回值是很是具備靈活性的,在須要的時候,能夠定義一個或者多個甚至選擇性的省略。

3.1 外部形參

  • Swift 語言也能支持 OC 的函數參數標籤模式,這種模式被稱爲外部形參。

    • 若是你爲參數制定了外部形參名,那麼在調用的時候就必須顯式的使用。
    • 若是別人第一次閱讀你的代碼,使用外部形參名稱可使你要表達的意思更加明確,上下文更加清晰。
    • 在函數調用時,若是你不想顯示形參名,可使用下劃線 _ 做爲外部形參名。
  • 定義格式

    // 使用時本地形參名(本地形參名一、本地形參名2, ...)會被省略
    func 函數名 (外部形參名1 本地形參名1: 參數類型, 外部形參名2 本地形參名2: 參數類型, ...) -> 函數返回類型 {
    
        函數體 .....
    
        return 返回值
    }
  • 在寫外部形參名時,徹底能夠只寫一次名字,只須要用一個 hash 符號 # 做爲參數名稱的前綴,從而告訴 Swift 咱們使用了名稱相同的本地形參名稱和外部形參名稱。

  • 定義格式

    func 函數名 (#參數名1: 參數類型, #參數名2: 參數類型, ...) -> 函數返回類型 {
    
        函數體 .....
    
        return 返回值
    }
    • 從 Swift 3.0 起再也不支持該種定義方式。

3.2 默認值形參

  • 在 Swift 語言中能夠爲任何形參定義默認值以做爲函數定義的一部分。

    • 若是已經定義了默認值,那麼調用函數時就能夠省略該形參。
    • 爲了不遺漏參數或者參數傳遞的二義性,需在函數形參列表的末尾放置帶默認值的形參,不要在非默認值的形參前放置。
    • 在有定義默認值的狀況下,當沒有指定外部形參名稱時,Swift 語言將爲你定義的任何默認值形參提供一個自動外部形參名,這個自動外部形參名和本地形參名相同。
  • 定義格式

    func 函數名 (參數名1: 參數類型, 參數名2: 參數類型, 默認值形參名: 參數類型 = 默認值) -> 函數返回類型 {
    
        函數體 .....
    
        return 返回值
    }

3.3 可變數量形參

  • 當不能肯定調用函數須要傳入具體參數的數量時,應使用可變形參。

  • 可變形參是指可接受零個或多個指定類型值的形參,能夠用它來傳遞任意數量的輸入參數。

    • 聲明可變形參時需在參數類型後面使用 ...
    • 當參數傳遞進函數體後,參數在函數體內能夠經過集合的形式訪問。
    • 一個函數最多能夠有一個可變參數,並且它必須出如今參數列表的最後。
  • 定義格式

    func 函數名 (參數名1: 參數類型, 參數名2: 參數類型, 可變形參名: 參數類型...) -> 函數返回類型 {
    
        函數體 .....
    
        return 返回值
    }
  • 可變數量形參的使用

    func arithmeticmean(numbers: Double...) -> Double {
        var total: Double = 0
        for number in numbers {
            total += number
        }
        return total / Double(numbers.count)
    }
    print(arithmeticmean(numbers: 1, 2, 3))              // 2.0
    print(arithmeticmean(numbers: 1, 2, 3, 4, 5))        // 3.0

3.4 可變值形參

  • Swift 語言函數的形參默認是常量,咱們不能直接在函數體內部改變形參的值,也就是說函數的形參默認是值類型的。

  • 可是若是須要在函數體內部修改函數參數值,可使用可變參數,

    • 要定義可變參數能夠在參數名前使用 var 關鍵字。
    • 可變參數可讓你可以修改形參的值,它能夠給函數體一個可修改的形參值副本。
    • 但這並不意味着可變形參就是引用類型的。
  • 雖然在 Swift 2.2 中仍舊可使用這個語法,可是在 Swift 3.0 中這種寫法已經被廢棄了,若是須要修改參數的值,能夠在函數體內建立新的成員變量。

  • 定義格式

    func 函數名 (var 參數名1: 參數類型, var 參數名2: 參數類型, ...) -> 函數返回類型 {
    
        函數體 .....
    
        return 返回值
    }

3.5 引用形參

  • 在實際的編碼中,咱們每每須要在函數體內部修改形參值,並同時做用到實參自己,從而省去增長返回值數量的步驟。

    • 這時能夠把形參定義爲 in-out(輸入輸出參數)類型。
    • Swift 3.0 以前,要定義 in-out 類型的參數,須要在參數名前使用 inout 關鍵字修飾。
    • Swift 3.0 及以後,要定義 in-out 類型的參數,須要在參數類型前使用 inout 關鍵字修飾。
    • 當把變量傳遞給 in-out 形參時,必須在變量前添加 「&」 符號,以代表他被函數內部修改的是它自己的引用。
  • 定義格式

    // Swift 3.0 以前
    func 函數名 (inout 參數名1: 參數類型, 參數名2: 參數類型, ...) {
    
        函數體 .....
    }
    // Swift 3.0 及以後
    func 函數名 (參數名1: inout 參數類型, 參數名2: 參數類型, ...) {
    
        函數體 .....
    }
  • 使用 in-out 參數的同時有幾條規則須要注意

    • 只能輸入一個變量做爲輸入輸出參數,不能將常量和字面量傳遞進函數。
    • 不能同時將參數標記爲 varletinout
    • 可變形參的參數不能標記爲 inout
    • 函數不能有默認值。
  • 引用形參的使用

    func exampleOfFunction(parameter: inout String) -> String {
        parameter = "Hello \(parameter)"
        return parameter
    }
    var name = "xiaoming"
    
    print(exampleOfFunction(parameter: &name))      // Hello xiaoming
    print(name)                                     // Hello xiaoming

四、嵌套函數

  • 在一個函數體中定義另一個函數體就稱爲嵌套函數。

    • 嵌套的函數默認對外是隱藏的,但仍能夠經過包裹他們的函數調用和使用它們。
  • 定義格式

    func 函數名1 (參數名1: 參數類型, 參數名2: 參數類型, ...) -> 函數返回類型1 {
    
        func 函數名2 (參數名3: 參數類型, 參數名4: 參數類型, ...) -> 函數返回類型2 {
    
            函數體2 .....
    
            return 返回值2
        }
    
        函數體1 .....
    
        return 返回值1
    }

五、函數重載

  • 在 Swift 中函數重載十分經常使用。

    • 因爲 Swift 是一門強類型語言,能夠修改參數列表或者使用不一樣的返回值實現函數重載。
    • 另外 Swift 中有一些特殊的函數是以操做符的形式定義的,好比 ==,若是想讓本身定義的數據結構可使用某個操做符,那麼能夠對操做符進行重載。
  • 參數列表重載的使用

    func test(s: Int) -> Int {
        print("Int")
        return 1
    }
    
    // 修改參數名
    func test(a: Int) -> Int {
        print("String")
        return 2
    }
    
    // 修改參數類型
    func test(s: String) -> Int {
        print("String")
        return 3
    }
    let intValue    = test(s: 0)         // 1
    let intValue    = test(a: 0)         // 2
    let stringValue = test(s: "")        // 3
    • 在調用函數時,編譯器會檢查函數所處的 「上下文」,肯定參數名和參數的類型,調用不一樣的實現。
  • 返回值重載的使用

    func test(s: String) -> Int {
        print("Int")
        return 3
    }
    
    // 修改返回值類型
    func test(s: String) -> String {
        print("String")
        return s
    }
    let intValue   : Int    = test(s: "")       // 3
    let stringValue: String = test(s: "")       // ""
    • 在調用函數時,編譯器會檢查函數所處的 「上下文」,肯定返回值的類型,調用不一樣的實現。
    • 由於函數存在多種 「上下文」,所以類型推斷再也不適用了。
    • 若是寫出下面的代碼編譯器會提示你明確 unKnow 的類型。

      let unKnow = test(s: "")
  • 操做符重載的使用

    struct BoxInt {
        var intValue: Int
    }
    
    func == (lhs: BoxInt, rhs: BoxInt) -> Bool {
        return lhs.intValue == rhs.intValue
    }
    let b1 = BoxInt(intValue: 1)
    let b2 = BoxInt(intValue: 2)
    
    print(b1 == b2)                 // false

五、函數風格

  • Swift 3.0 以後,函數風格發生了較大的變化,這主要是受 Swift 3.0 提出的 API 設計原則的影響。

  • 1)縮減函數名

    • 在 Swift 3.0 以前,Swift 的函數風格與 OC 相似,函數名須要承擔描述首個參數的職責,在函數調用時,函數中首個參數的參數名默認會被隱藏,只在函數體中使用。
    • 從 Swift 3.0 開始,函數的首個參數名再也不默認被隱藏,你能夠把函數的方法名縮減,把關鍵字轉移到首個參數的參數名上。

      // Swift 3.0 以前
      arr.appendContentsof([4, 5])
      
      // Swift 3.0 及以後
      arr.append(contentsOf: [4, 5])
      • 這樣不管是添加單個元素,仍是添加整個數組的方法都統一爲 append,API 更加整齊。
  • 2)用 「時態」 表示函數 「反作用」

    • 在一般的認知中,函數應該是 「無狀態」 的,也就是說,不管調用多少次都能獲得相同的結果,可是,有時候函數體內部也會修改函數外部的成員值。

      var mutableArr = [1, 3, 2]
      
      // 在 Swift 3.0 以前,sort 方法叫作 sortInPlace
      mutableArr.sort()
      
      // sorted 是 sort 的反作用版本
      let immutableArr = mutableArr.sorted()
      • sort 是動詞時態,表明這個方法沒有反作用,也就是說,sort 方法只會對方法的調用者起做用,是一種原地排序。
      • sortedsort 方法的反作用版本,sorted 方法不會修改原數組,會把原數組拷貝後排序,而且返回排序好的數組,你能夠把返回值理解成一種反作用。
  • 3)關鍵字能夠用做參數名

    • 從 Swift 3.0 開始,大多數 Swift 關鍵字均可以被用做參數名。

      func index(for element: Int, in collection: [Int]) -> Int? {
          for (num, e) in collection.enumerated() {
              if e == element {
                  return num
              }
          }
          return nil
      }
      index(for: 3, in: [1, 2, 2, 2, 3])            // 4
      • for-in 關鍵字本來是用在循環中,在這裏被用做函數的外部參數名。
相關文章
相關標籤/搜索