//***********************************
//
// 关联类型
// 20150106我的理解:类似是协议里面的泛型类型
// 定义协议时使用关联类型,就不必指定专门的类型,灵活性更高
//
//***********************************
//
// 下面的例子里,Container协议定义了一个ItemType关联类型和三个兼容要求
// 1.能通过append方法添加一个新item到Container
// 2.能使用count返回数值:例子里是返回Container里面items的数量
// 3.能通过Container的下标获取到类型=ItemType的一个值
//
//***********************************
protocol Container {
typealias ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
struct IntStack: Container {
var items = [Int]()
mutating func push(item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
//下面是遵循Container协议
typealias ItemType = Int
//下面的ItemType用Int代替同样生效
mutating func append(item: ItemType) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> ItemType {
return items[i]
}
}
//改写成泛型类型
struct Stack<T>:Container{
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
typealias ItemType = T
mutating func append(item: ItemType) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> ItemType {
return items[i]
}
}
//***********************************
//
// 由上述可见,数组Array其实是符合Container协议的,只要进行一个空扩展,
// 即可将Array当做Container来使用
//
//***********************************
extension Array : Container {}
//*************************************
//
// Where子句
// where语句能够要求一个关联类型遵循特定的协议
//
//*************************************
func allItemsMatch<
C1:Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, anotherContainer: C2 ) -> Bool {
if someContainer.count != anotherContainer.count {
return false
}
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
return true
}