Swift泛型类型
泛型类型
通常在泛型函数中,Swift 允许你定义你自己的泛型类型。这些自定义类、结构体和枚举作用于任何类型,如同Array
和Dictionary
的用法。
这部分向你展示如何写一个泛型集类型--Stack
(栈)。一个栈是一系列值域的集合,和Array
(数组)类似,但其是一个比 Swift 的Array
类型更多限制的集合。一个数组可以允许其里面任何位置的插入/删除操作,而栈,只允许在集合的末端添加新的项(如同push一个新值进栈)。同样的一个栈也只能从末端移除项(如同pop一个值出栈)。
注意
栈的概念已被UINavigationController
类使用来模拟试图控制器的导航结构。你通过调用UINavigationController
的pushViewController:animated:
方法来为导航栈添加(add)新的试图控制器;而通过popViewControllerAnimated:
的方法来从导航栈中移除(pop)某个试图控制器。每当你需要一个严格的后进先出
方式来管理集合,堆栈都是最实用的模型。
下图展示了一个栈的压栈(push)/出栈(pop)的行为:
- 现在有三个值在栈中;
- 第四个值“pushed”到栈的顶部;
- 现在有四个值在栈中,最近的那个在顶部;
- 栈中最顶部的那个项被移除,或称之为“popped”;
- 移除掉一个值后,现在栈又重新只有三个值。
这里展示了如何写一个非泛型版本的栈,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
数组。
上面所展现的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
的泛型版本基本上和非泛型版本相同,但是泛型版本的占位类型参数为T代替了实际Int
类型。这种类型参数包含在一对尖括号里(<T>
),紧随在结构体名字后面。
T
定义了一个名为“某种类型T”的节点提供给后来用。这种将来类型可以在结构体的定义里任何地方表示为“T”。在这种情况下,T
在如下三个地方被用作节点:
-
创建一个名为
items
的属性,使用空的T类型值数组对其进行初始化; -
指定一个包含一个参数名为
item
的push
方法,该参数必须是T类型; -
指定一个
pop
方法的返回值,该返回值将是一个T类型值。
当创建一个新单例并初始化时, 通过用一对紧随在类型名后的尖括号里写出实际指定栈用到类型,创建一个Stack
实例,同创建Array
和Dictionary
一样:
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cuatro")
// 现在栈已经有4个string了
下图将展示stackOfStrings
如何push
这四个值进栈的过程:
从栈中pop
并移除值"cuatro":
let fromTheTop = stackOfStrings.pop()
// fromTheTop is equal to "cuatro", and the stack now contains 3 strings
下图展示了如何从栈中pop一个值的过程:
由于Stack
是泛型类型,所以在 Swift 中其可以用来创建任何有效类型的栈,这种方式如同Array
和Dictionary
。