//***********************************
//
// 關聯類型
// 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
}