//***********swift学习之29--泛型--***************************
/*
Swift 提供了泛型让你写出灵活且可重用的函数和类型。
Swift 标准库是通过泛型代码构建出来的。
Swift 的数组和字典类型都是泛型集。
*/
// 定义一个交换两个变量的函数
/*
声明函数时,在参数前面用inout修饰,在函数内部实现改变外部参数,注意,这里只能传入变量,不能传入常量和字面量,因为这些是不能变的一旦定义,当我们传入的时候,在变量名字前面用&符号修饰表示,传递给inout参数,表明这个变量在参数内部是可以被改变的
注意:inout修饰的参数是不能有默认值的,有范围的参数集合也不能被修饰,另外,一个参数一旦被inout修饰,就不能再被var和let修饰了
*/
// 泛型函数可以访问任何类型,如 Int 或 String。
// 以下实例是一个泛型函数 exchange 用来交换两个 Int 和 String 值:
func exchange<T>( a: inout T, b: inout T) {
let temp = a
a = b
b = temp
}
var numb1 = 100
var numb2 = 200
print("交换前数据: \(numb1) 和 \(numb2)")
exchange(a: &numb1, b: &numb2)
print("交换后数据: \(numb1) 和 \(numb2)")
var str1 = "A"
var str2 = "B"
print("交换前数据: \(str1) 和 \(str2)")
exchange(a: &str1, b: &str2)
print("交换后数据: \(str1) 和 \(str2)")
/*
扩展泛型类型
当你扩展一个泛型类型的时候(使用 extension 关键字),你并不需要在扩展的定义中提供类型参数列表。更加方便的是,原始类型定义中声明的类型参数列表在扩展里是可以使用的,并且这些来自原始类型中的参数名称会被用作原始定义中类型参数的引用。
实例
下面的例子扩展了泛型 TOS 类型,为其添加了一个名为 first 的只读计算属性,它将会返回当前栈顶端的元素而不会将其从栈中移除。
*/
// Swift 允许你定义你自己的泛型类型。
// 自定义类、结构体和枚举作用于任何类型,如同Array和Dictionary的用法。
struct TOS<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var tos = TOS<String>()
tos.push(item: "Swift")
print(tos.items)
tos.push(item: "泛型")
print(tos.items)
tos.push(item: "类型参数")
print(tos.items)
tos.push(item: "类型参数名")
print(tos.items)
// 扩展泛型 TOS 类型
extension TOS {
var first: T? {
return items.isEmpty ? nil : items[items.count - 1]
}
}
if let first = tos.first {
print("栈顶部项:\(first)")
}
/*
Where 语句
类型约束能够确保类型符合泛型函数或类的定义约束。
你可以在参数列表中通过where语句定义参数的约束。
你可以写一个where语句,紧跟在在类型参数列表后面,where语句后跟一个或者多个针对关联类型的约束,以及(或)一个或多个类型和关联类型间的等价(equality)关系。
实例
下面的例子定义了一个名为allItemsMatch的泛型函数,用来检查两个Container实例是否包含相同顺序的相同元素。
如果所有的元素能够匹配,那么返回一个为true的Boolean值,反之则为false。
*/
protocol Container {
associatedtype ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
// original Stack<T> implementation
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(item: T) {
self.push(item: item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> T {
return items[i]
}
}
func allItemsMatch<
C1: Container, C2: Container>
(someContainer: C1, anotherContainer: C2) -> Bool
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable {
// 检查两个Container的元素个数是否相同
if someContainer.count != anotherContainer.count {
return false
}
// 检查两个Container相应位置的元素彼此是否相等
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
// 匹配所有项,返回 true
return true
}
var tos111 = Stack<String>()
tos111.push(item: "Swift")
print(tos111.items)
tos111.push(item: "泛型")
print(tos111.items)
tos111.push(item: "Where 语句")
print(tos111.items)
var tos222 = Stack<String>()
tos222.push(item: "Swift")
print(tos222.items)
tos222.push(item: "泛型")
print(tos222.items)
tos222.push(item: "Where 语句")
print(tos222.items)
//var eos = ["Swift", "泛型", "Where 语句"]
//print(eos)
allItemsMatch(someContainer:tos111,anotherContainer:tos222)