方法終于成為了一等公民,也就是說涩馆,我們可以將方法當(dāng)作變量或者參數(shù)來使用了。更進(jìn)一步地允坚,我們甚至可以在一個方法中定義新的方法魂那,這給代碼結(jié)構(gòu)層次和訪問級別的控制帶來了新的選擇。
想想看有多少次我們因?yàn)橐粋€方法主體內(nèi)容過長稠项,而不得不將它重構(gòu)為好幾個小的功能塊的方法涯雅,然后在原來的主體方法中去調(diào)用這些小方法。這些具體負(fù)責(zé)一個個小功能塊的方法也許一輩子就被調(diào)用這么一次展运,但是卻不得不存在于整個類型的作用域中活逆。雖然我們會將它們標(biāo)記為私有方法,但是事實(shí)上它們所承擔(dān)的任務(wù)往往和這個類型沒有直接關(guān)系乐疆,而只是會在這個類型中的某個方法中被用到划乖。更甚至這些小方法也可能有些復(fù)雜,我們還想進(jìn)一步將它們分成更小的模塊挤土,我們很可能也只有將它們放到和其他方法平級的地方琴庵。這樣一來,本來應(yīng)該是進(jìn)深的結(jié)構(gòu),卻被整個展平了迷殿,導(dǎo)致之后在對代碼的理解和維護(hù)上都很成問題儿礼。在 Swift 中,我們對于這種情況有了很好的應(yīng)對庆寺,我們可以在方法中定義其他方法蚊夫,也就是說讓方法嵌套起來。
舉個例子懦尝,我們在寫一個網(wǎng)絡(luò)請求的類 Request
時知纷,可能面臨著將請求的參數(shù)編碼到 url 里的任務(wù)。因?yàn)檩斎氲膮?shù)可能包括單個的值陵霉,字典琅轧,或者是數(shù)組,因此為了結(jié)構(gòu)漂亮和保持方法短小踊挠,我們可能將情況分開乍桂,寫出這樣的代碼:
func appendQuery(url: String,
key: String,
value: AnyObject) -> String {
if let dictionary = value as? [String: AnyObject] {
return appendQueryDictionary(url: url, key: key, value: dictionary)
} else if let array = value as? [AnyObject] {
return appendQueryArray(url: url, key: key, value: array)
} else {
return appendQuerySingle(url: url, key: key, value: value)
}
}
func appendQueryDictionary(url: String,
key: String,
value: [String: AnyObject]) -> String {
//...
return ""
}
func appendQueryArray(url: String,
key: String,
value: [AnyObject]) -> String {
//...
return ""
}
func appendQuerySingle(url: String,
key: String,
value: AnyObject) -> String {
//...
return ""
}
事實(shí)上后三個方法都只會在第一個方法中被調(diào)用,它們其實(shí)和 Request
沒有直接的關(guān)系效床,所以將它們放到 appendQuery
中去會是一個更好的組織形式:
func appendQuery(url: String,
key: String,
value: AnyObject) -> String {
func appendQueryDictionary(url: String,
key: String,
value: [String: AnyObject]) -> String {
//...
return ""
}
func appendQueryArray(url: String,
key: String,
value: [AnyObject]) -> String {
//...
return ""
}
func appendQuerySingle(url: String,
key: String,
value: AnyObject) -> String {
//...
return ""
}
if let dictionary = value as? [String: AnyObject] {
return appendQueryDictionary(url: url, key: key, value: dictionary)
} else if let array = value as? [AnyObject] {
return appendQueryArray(url: url, key: key, value: array)
} else {
return appendQuerySingle(url: url, key: key, value: value)
}
}
另一個重要的考慮是雖然 Swift 提供了 public睹酌,internal 和 private
三種訪問權(quán)限,但是有些方法我們完全不希望在其他地方被直接使用剩檀。最常見的例子就是在方法的模板中:我們一方面希望靈活地提供一個模板來讓使用者可以通過模板定制他們想要的方法憋沿,但另一方面又不希望暴露太多實(shí)現(xiàn)細(xì)節(jié),或者甚至是讓使用者可以直接調(diào)用到模板谨朝。一個最簡單的例子就是類似這樣的代碼:
func makeIncrementor(addNumber: Int) -> ((inout Int) -> Void) {
func incrementor(variable: inout Int) -> Void {
variable += addNumber;
}
return incrementor;
}