最近真正開始學 Swift标锄,在調(diào)用函數(shù)的時候遇到一個問題:到底寫不寫函數(shù)名?
我們來看兩個個例子:
// 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)
四處調(diào)用星压,哪個會報錯践剂?
請
仔
細
思
考
一
下
,
或
者
打
開
Playground
運
行
一
下
租幕。
好吧舷手,如果你還是直接翻到這里,那我也無能為力了劲绪。
答案是:四處全部報錯。
正確的寫法是:
test(1, 1)
var test = Test(name: "Jack", age: 12)
test.sayHello("nice to meet you", place: "Beijing")
腳麻了嗎盆赤?麻了就對了贾富,我跺我也麻。
到底咋回事
首先我們要清楚牺六,Swift 中的調(diào)用有三種:
- 函數(shù)調(diào)用(閉包也歸于函數(shù)颤枪,雖然所有函數(shù)本質(zhì)上都是閉包。這句話看不懂的自動跳過淑际,只是為了防人摳字眼)
- 類初始化
- 方法調(diào)用
如果沒有參數(shù)畏纲,那自然直接()
調(diào)用,因此下面的討論前提是需要傳參春缕,并且傳參數(shù)量大于一盗胀。
上一節(jié)的例子就是典型的三種調(diào)用,傳參的時候正確寫法如下:
<函數(shù)名>(參數(shù)值锄贼,參數(shù)值...) // 不加任何參數(shù)名票灰,直接寫參數(shù)值
<實例>.<方法名>(參數(shù)值,參數(shù)名:參數(shù)值,參數(shù)名:參數(shù)值...) // 方法調(diào)用第一個參數(shù)不寫參數(shù)名屑迂,后面的全部要寫浸策。特殊情況是尾閉包,往下看
<類初始化>(參數(shù)名:參數(shù)值惹盼,參數(shù)名:參數(shù)值...) // 類初始化所有參數(shù)都需要加參數(shù)名
單個函數(shù)的調(diào)用很好理解庸汗,其他語言里也大多是這么做的。我們主要解釋方法調(diào)用和類初始化這兩種調(diào)用手报。
為什么 Swift 對方法調(diào)用和類初始化的參數(shù)名有如此奇怪的限制夫晌?主要原因是繼承 Objective-C 的一貫傳統(tǒng)。我們來看看 OC 里面的寫法:
[person setName:@"sam" andSecondName:@"job"]
setName
是方法名昧诱,后面緊跟第一個參數(shù)晓淀,對應 Swift 中的寫法是:
person.setName("sam", andSecondName: "job")
也就是說,方法名中已經(jīng)隱含了第一個參數(shù)的名字(雖然我們不知道第一個參數(shù)名是什么盏档,但是顯然第一個參數(shù)是Name
凶掰,我們就可以知道第一個參數(shù)是名字),所以省略第一個參數(shù)名蜈亩。
那么init
為什么要加上第一個參數(shù)名懦窘?
直接看代碼:
[Test initWith:"Sam", andSecondName: "job"] // oc
Test(name: "Sam", andSecondName: "job") / swift
由于 Swift 中初始化時候直接使用類名,沒有方法名稚配,所以第一個參數(shù)名就不能省略了畅涂。
特殊情況
下面介紹幾種特殊情況。
尾閉包
首先是尾閉包道川。
Swift 中許多方法的最后一個參數(shù)是handler
午衰,我們可以傳入一個閉包。由于閉包寫到參數(shù)列表里比較繁瑣冒萄,Swift 提供了一種新寫法:尾閉包臊岸。看例子:
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) {
......
})
UIAlertAction
的最后一個參數(shù)是handler
尊流,這里用尾閉包來寫的話帅戒,就是在右括號后面直接加閉包。當然崖技,你也可以把閉包寫到參數(shù)列表里逻住,只是需要加參數(shù)名。
如果函數(shù)只需要handler
一個參數(shù)迎献,可以省略方法調(diào)用的圓括號:
aaa.sort {
...
}
默認值
參數(shù)可以寫默認值瞎访,但是默認值有許多規(guī)矩:
- 如果使用默認值,調(diào)用的時候忿晕,默認值對應的參數(shù)必須寫參數(shù)名装诡。這里影響的主要是函數(shù)和方法調(diào)用银受,因為類初始化本來就要寫全參數(shù)名。
- 如果使用默認值并且默認值不是出現(xiàn)在最后鸦采,那調(diào)用的時候必須寫全所有參數(shù)宾巍。
綜合以上兩點,建議大家在使用默認值的時候渔伯,把帶默認值的參數(shù)放在列表結尾顶霞,這樣會方便許多。
強制指定參數(shù)名
如果你想強制要求調(diào)用時必須加參數(shù)名锣吼,可以在聲明的時候給參數(shù)加上外部參數(shù)名:
func test(outName name: String, outAge age: Int) {
...
}
test(outName: "asd", outAge: 2)
這樣調(diào)用的時候必須加上對應的外部參數(shù)名选浑。
如果外部參數(shù)名和內(nèi)部參數(shù)名一樣,可以直接在參數(shù)名前加#
:
func test(#name: String, #age: Int) {
...
}
test(outName: "asd", outAge: 2)
強制取消參數(shù)名
對于需要參數(shù)名的函數(shù)玄叠,你也可以在參數(shù)名前加_
來強制取消參數(shù)名:
class Test {
func test(name: String, _ age: Int) {
...
}
}
var test = Test()
test.test("123", 3)
總之
Swift 中的函數(shù)調(diào)用真是個坑古徒。