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

這里展示了如何寫一個非泛型版本的棧,Int值型的棧:
struct IntStack {
var items = Int[]()
mutating func push(item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
}
這個結構體在棧中使用一個Array性質的items存儲值。Stack提供兩個方法:push和pop,從棧中壓進一個值和移除一個值。這些方法標記為可變的,因為它們需要修改(或轉換)結構體的items數(shù)組。
上面所展現(xiàn)的IntStack類型只能用于Int值,不過,其對于定義一個泛型Stack類(可以處理任何類型值的棧)是非常有用的。
這里是一個相同代碼的泛型版本:
struct Stack<T> {
var items = T[]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
注意到Stack的泛型版本基本上和非泛型版本相同,但是泛型版本的占位類型參數(shù)為T代替了實際Int類型。這種類型參數(shù)包含在一對尖括號里(<T>),緊隨在結構體名字后面。
T定義了一個名為“某種類型T”的節(jié)點提供給后來用。這種將來類型可以在結構體的定義里任何地方表示為“T”。在這種情況下,T在如下三個地方被用作節(jié)點:
items的屬性,使用空的T類型值數(shù)組對其進行初始化;item的push方法,該參數(shù)必須是T類型;pop方法的返回值,該返回值將是一個T類型值。
當創(chuàng)建一個新單例并初始化時, 通過用一對緊隨在類型名后的尖括號里寫出實際指定棧用到類型,創(chuàng)建一個Stack實例,同創(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個string了
下圖將展示stackOfStrings如何push這四個值進棧的過程:

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