//非泛型函数
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
func swapTwoStrings(_ a: inout String, _ b: inout String) {
let temporaryA = a
a = b
b = temporaryA
}
//泛型函数
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
<T>
)第一个类型参数A,A必须是ClassA子类的类型约束
第二个类型参数B,B必须符合ClassB协议的类型约束
func doSomething<A:ClassA,B:ClassB>(someA:A someB:B){
}
associatedtype
关键字来指定关联类型protocol Container {
associatedtype ItemType
mutating func append(_ item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
这个协议没有指定元素必须是何种类型,为了满足这三个条件,Container 协议需要在不知道容器中元素的具体类型的情况下引用这种类型。Container 协议需要指定任何通过 append(_:) 方法添加到容器中的元素和容器中的元素是相同类型,并且通过容器下标返回的元素的类型也是这种类型,为了达到这个目的,Container 协议声明了一个关联类型 ItemType,写作 associatedtype ItemType。这个协议无法定义 ItemType 是什么类型的别名,这个信息将留给遵从协议的类型来提供
struct Stack<Element>: Container {
// Stack<Element> 的原始实现部分
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
// Container 协议的实现部分
mutating func append(_ item: Element) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Element {
return items[i]
}
}
下面这个泛型函数在类型参数里面添加了where
子句约束,C1,C2都必须是采纳Container
协议的类型,并且C1、C2的泛型类型必须相同,而且C1的泛型类型必须是符合Equatable
的
protocol Container{
typealias itemType
mutating func append(item:itemType)
var count:Int{get}
subscript(i:Int)->itemType {get}
}
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-1{
if someContainer[i] != anotherContainer[i]{
return false
}
}
return true
}