泛型能讓我們使用的類型和函數(shù)使用未知的類型,許多內(nèi)置類型罢浇,例如可空類型陆赋,數(shù)組和字典都是用泛型實現(xiàn)的。
泛型類型
下面的結(jié)構(gòu)體實現(xiàn)了一個簡單的棧嚷闭,可以對Int類型執(zhí)行push和pop操作攒岛。
struct Stack{
var items = [Int]()
mutating func push(newitem:Int){
items.append(newitem)
}
mutating func pop() ->Int?{
guard !items.isEmpty else{
return nil
}
return items.removeLast()
}
}
var stack=Stack()
stack.push(newitem:1)
stack.push(newitem:2)
print(stack.pop())
print(stack.pop())
但是如果我們需要對其他類型進行入棧和出棧操作,那就得再編寫一個棧類型胞锰,使用泛型可以讓這個棧支持任意類型灾锯。改寫后的代碼如下,Swift的泛型語法和Java差不多嗅榕。
struct Stack<T>{
var items = [T]()
mutating func push(newitem:T){
items.append(newitem)
}
mutating func pop() ->T?{
guard !items.isEmpty else{
return nil
}
return items.removeLast()
}
}
var stack=Stack<Int>()
stack.push(newitem:1)
stack.push(newitem:2)
print(stack.pop())
print(stack.pop())
多個占位類型
泛型可支持多個占位類型顺饮,代碼如下。
struct Stack<T,U,X>{
var items = [T]()
var items1 = [U]()
var items2 = [X]()
...
}
var stack=Stack<Int,String,Double>()
泛型函數(shù)和方法
泛型函數(shù)需要在函數(shù)參數(shù)列表前聲明占位類型凌那,然后可以在參數(shù)和返回值中使用這些占位類型兼雄。
func getSelf<T>(arg:T)->T{
return arg
}
print(getSelf(arg: "hello world!"))
類型約束
有時候我們需要對傳入的類型做一些限制,可以通過類型約束實現(xiàn)帽蝶,有兩種約束:一種是類型必須是給定類的子類赦肋,還有一種是類型必須符合一個協(xié)議。
func checkEqual<T:Equatable>(first:T,second:T)->Bool{
return first==second
}
print(checkEqual(first: 1, second: 1))
print(checkEqual(first: "123", second: "456"))
當占位類型比較復雜時励稳,我們還可以使用where語句進一步約束占位類型佃乘,如下代碼要求newitems的元素必須是T類型。
struct Stack<T>{
var items = [T]()
mutating func push(newitem:T){
items.append(newitem)
}
mutating func pushAll<S:Sequence>(newitems:S)
where S.Iterator.Element==T {
for item in newitems {
self.push(newitem: item)
print("push \(item)")
}
}
mutating func pop() ->T?{
guard !items.isEmpty else{
return nil
}
return items.removeLast()
}
}
var stack=Stack<Int>()
stack.pushAll(newitems:[1,2,3,4,5,6])
關(guān)聯(lián)類型協(xié)議
協(xié)議不支持泛型驹尼,但是支持另外一種特性:關(guān)聯(lián)類型趣避,在協(xié)議內(nèi)部可以使用associatedtype關(guān)鍵字聲明一個占位類型,符合這個協(xié)議的類型應該在其內(nèi)部為占位類型提供typealias定義新翎。
protocol InteratorProtocol {
associatedtype Element
mutating func next() -> Element?
}
struct Stack<T>:InteratorProtocol {
typealias Element = Int
mutating func next() -> Element? {
return 0
}
}