本文主要介绍泛型及其底层原理
泛型
泛型主要用于解决代码的抽象能力
+ 代码的复用性
例如下面的例子,其中的T就是泛型
func test<T>(_ a: T, _ b: T)->Bool{
return a == b
}
//经典例子swap,使用泛型,可以满足不同类型参数的调用
func swap<T>(_ a: inout T, _ b: inout T){
let tmp = a
a = b
b = tmp
}
类型约束
在一个类型参数后面放置协议或者是类,例如下面的例子,要求类型参数T遵循Equatable协议
func test<T: Equatable>(_ a: T, _ b: T)->Bool{
return a == b
}
当传入的参数是没有遵循Equatable
协议时,会报错
关联类型
在定义协议时,使用关联类型
给协议中用到的类型
起一个占位符名称
- 此时的数组中的类型是Int
struct CJLStack {
private var items = [Int]()
mutating func push(_ item: Int){
items.append(item)
}
mutating func pop() -> Int?{
if items.isEmpty {
return nil
}
return items.removeLast()
}
}
- 如果想使用其他类型呢?可以
通过协议来实现
protocol CJLStackProtocol {
//协议中使用类型的占位符
associatedtype Item
}
struct CJLStack: CJLStackProtocol{
//在使用时,需要指定具体的类型
typealias Item = Int
private var items = [Item]()
mutating func push(_ item: Item){
items.append(item)
}
mutating func pop() -> Item?{
if items.isEmpty {
return nil
}
return items.removeLast()
}
}
where语句
where语句主要用于 表明泛型需要满足的条件
,即限制形式参数的要求,如下所示
//***********3、where语句:表明泛型需要满足的条件
protocol CJLStackProtocol {
//协议中使用类型的占位符
associatedtype Item
var itemCount: Int {get}
mutating func pop() -> Item?
func index(of index: Int) -> Item
}
struct CJLStack: CJLStackProtocol{
//在使用时,需要指定具体的类型
typealias Item = Int
private var items = [Item]()
var itemCount: Int{
get{
return items.count
}
}
mutating func push(_ item: Item){
items.append(item)
}
mutating func pop() -> Item?{
if items.isEmpty {
return nil
}
return items.removeLast()
}
func index(of index: Int) -> Item {
return items[index]
}
}
/*
where语句
- T1.Item == T2.Item 表示T1和T2中的类型必须相等
- T1.Item: Equatable 表示T1的类型必须遵循Equatable协议,意味着T2也要遵循Equatable协议
*/
func compare<T1: CJLStackProtocol, T2: CJLStackProtocol>(_ stack1: T1, _ stack2: T2) -> Bool where T1.Item == T2.Item, T1.Item: Equatable{
guard stack1.itemCount == stack2.itemCount else {
return false
}
for i in 0..<stack1.itemCount {
if stack1.index(of: i) != stack2.index(of: i){
return false
}
}
return true
下面这种写法也是可以的
//写法二
protocol CJLStackProtocol {
//协议中使用类型的占位符
associatedtype Item
var itemCount: Int {get}
mutating func pop() -> Item?
func index(of index: Int) -> Item
}
struct CJLStack: CJLStackProtocol{
//在使用时,需要指定具体的类型