Swift 函數調用到底寫不寫參數名


最近真正開始學 Swift,在調用函數的時候遇到一個問題:到底寫不寫函數名?

我們來看兩個個例子:

// 1 func test(a: Int, b: Int) ->Int { return a + b } test(a: 1, b: 1) // (A) test(1, b:1) // (B) //2 class Test { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } func sayHello(word: String, place: String) { println("Hello \(self.name), \(word) at \(place)") } } var test = Test("Jack", age: 12) // (C) test.sayHello(word: "nice to meet you", place: "Beijing") // (D)

(A)(B)(C)(D)四處調用,哪個會報錯?













Playground




好吧,如果你還是直接翻到這里,那我也無能為力了。

答案是:四處全部報錯。

正確的寫法是:

test(1, 1) var test = Test(name: "Jack", age: 12) test.sayHello("nice to meet you", place: "Beijing")

腳麻了嗎?麻了就對了,我跺我也麻。


我這智商基本告別 Swift 了

到底咋回事


首先我們要清楚,Swift 中的調用有三種:

  • 函數調用(閉包也歸於函數,雖然所有函數本質上都是閉包。這句話看不懂的自動跳過,只是為了防人摳字眼)
  • 類初始化
  • 方法調用

如果沒有參數,那自然直接()調用,因此下面的討論前提是需要傳參,並且傳參數量大於一。

上一節的例子就是典型的三種調用,傳參的時候正確寫法如下:

<函數名>(參數值,參數值...) // 不加任何參數名,直接寫參數值 <實例>.<方法名>(參數值,參數名:參數值,參數名:參數值...) // 方法調用第一個參數不寫參數名,后面的全部要寫。特殊情況是尾閉包,往下看 <類初始化>(參數名:參數值,參數名:參數值...) // 類初始化所有參數都需要加參數名

單個函數的調用很好理解,其他語言里也大多是這么做的。我們主要解釋方法調用和類初始化這兩種調用。

為什么 Swift 對方法調用和類初始化的參數名有如此奇怪的限制?主要原因是繼承 Objective-C 的一貫傳統。我們來看看 OC 里面的寫法:

 [person setName:@"sam" andSecondName:@"job"]

setName是方法名,后面緊跟第一個參數,對應 Swift 中的寫法是:

person.setName("sam", andSecondName: "job")

也就是說,方法名中已經隱含了第一個參數的名字(雖然我們不知道第一個參數名是什么,但是顯然第一個參數是Name,我們就可以知道第一個參數是名字),所以省略第一個參數名。

那么init為什么要加上第一個參數名?

直接看代碼:

[Test initWith:"Sam", andSecondName: "job"] // oc Test(name: "Sam", andSecondName: "job") / swift

由於 Swift 中初始化時候直接使用類名,沒有方法名,所以第一個參數名就不能省略了。

特殊情況


下面介紹幾種特殊情況。

尾閉包

首先是尾閉包。

Swift 中許多方法的最后一個參數是handler,我們可以傳入一個閉包。由於閉包寫到參數列表里比較繁瑣,Swift 提供了一種新寫法:尾閉包。看例子:

alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) { ...... })

UIAlertAction的最后一個參數是handler,這里用尾閉包來寫的話,就是在右括號后面直接加閉包。當然,你也可以把閉包寫到參數列表里,只是需要加參數名。

如果函數只需要handler一個參數,可以省略方法調用的圓括號:

aaa.sort { ... }

默認值

參數可以寫默認值,但是默認值有許多規矩:

  • 如果使用默認值,調用的時候,默認值對應的參數必須寫參數名。這里影響的主要是函數和方法調用,因為類初始化本來就要寫全參數名。
  • 如果使用默認值並且默認值不是出現在最后,那調用的時候必須寫全所有參數。

綜合以上兩點,建議大家在使用默認值的時候,把帶默認值的參數放在列表結尾,這樣會方便許多。

強制指定參數名

如果你想強制要求調用時必須加參數名,可以在聲明的時候給參數加上外部參數名:

func test(outName name: String, outAge age: Int) { ... } test(outName: "asd", outAge: 2)

這樣調用的時候必須加上對應的外部參數名。

如果外部參數名和內部參數名一樣,可以直接在參數名前加#

func test(#name: String, #age: Int) { ... } test(outName: "asd", outAge: 2)

強制取消參數名

對於需要參數名的函數,你也可以在參數名前加_來強制取消參數名:

class Test { func test(name: String, _ age: Int) { ... } } var test = Test() test.test("123", 3)

總之

Swift 中的函數調用真是個坑。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM