通常在泛型函數(shù)中,Swift 允許你定義你自己的泛型類型。這些自定義類、結(jié)構(gòu)體和枚舉作用于任何類型,如同Array和Dictionary的用法。
這部分向你展示如何寫一個(gè)泛型集類型--Stack(棧)。一個(gè)棧是一系列值域的集合,和Array(數(shù)組)類似,但其是一個(gè)比 Swift 的Array類型更多限制的集合。一個(gè)數(shù)組可以允許其里面任何位置的插入/刪除操作,而棧,只允許在集合的末端添加新的項(xiàng)(如同push一個(gè)新值進(jìn)棧)。同樣的一個(gè)棧也只能從末端移除項(xiàng)(如同pop一個(gè)值出棧)。
注意
棧的概念已被UINavigationController類使用來(lái)模擬試圖控制器的導(dǎo)航結(jié)構(gòu)。你通過(guò)調(diào)用UINavigationController的pushViewController:animated:方法來(lái)為導(dǎo)航棧添加(add)新的試圖控制器;而通過(guò)popViewControllerAnimated:的方法來(lái)從導(dǎo)航棧中移除(pop)某個(gè)試圖控制器。每當(dāng)你需要一個(gè)嚴(yán)格的后進(jìn)先出方式來(lái)管理集合,堆棧都是最實(shí)用的模型。
下圖展示了一個(gè)棧的壓棧(push)/出棧(pop)的行為:

這里展示了如何寫一個(gè)非泛型版本的棧,Int值型的棧:
struct IntStack {
var items = Int[]()
mutating func push(item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
}
這個(gè)結(jié)構(gòu)體在棧中使用一個(gè)Array性質(zhì)的items存儲(chǔ)值。Stack提供兩個(gè)方法:push和pop,從棧中壓進(jìn)一個(gè)值和移除一個(gè)值。這些方法標(biāo)記為可變的,因?yàn)樗鼈冃枰薷?或轉(zhuǎn)換)結(jié)構(gòu)體的items數(shù)組。
上面所展現(xiàn)的IntStack類型只能用于Int值,不過(guò),其對(duì)于定義一個(gè)泛型Stack類(可以處理任何類型值的棧)是非常有用的。
這里是一個(gè)相同代碼的泛型版本:
struct Stack<T> {
var items = T[]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
注意到Stack的泛型版本基本上和非泛型版本相同,但是泛型版本的占位類型參數(shù)為T代替了實(shí)際Int類型。這種類型參數(shù)包含在一對(duì)尖括號(hào)里(<T>),緊隨在結(jié)構(gòu)體名字后面。
T定義了一個(gè)名為“某種類型T”的節(jié)點(diǎn)提供給后來(lái)用。這種將來(lái)類型可以在結(jié)構(gòu)體的定義里任何地方表示為“T”。在這種情況下,T在如下三個(gè)地方被用作節(jié)點(diǎn):
items的屬性,使用空的T類型值數(shù)組對(duì)其進(jìn)行初始化;item的push方法,該參數(shù)必須是T類型;pop方法的返回值,該返回值將是一個(gè)T類型值。
當(dāng)創(chuàng)建一個(gè)新單例并初始化時(shí), 通過(guò)用一對(duì)緊隨在類型名后的尖括號(hào)里寫出實(shí)際指定棧用到類型,創(chuàng)建一個(gè)Stack實(shí)例,同創(chuàng)建Array和Dictionary一樣:
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cuatro")
// 現(xiàn)在棧已經(jīng)有4個(gè)string了
下圖將展示stackOfStrings如何push這四個(gè)值進(jìn)棧的過(guò)程:

從棧中pop并移除值"cuatro":
let fromTheTop = stackOfStrings.pop()
//