iOS开发-Swift进阶之泛型!

本文深入探讨Swift中的泛型,包括类型约束、关联类型和where语句。通过源码分析和调试,揭示泛型函数的内存管理和类型处理。泛型在提升代码复用和类型安全性方面发挥关键作用,同时也详细阐述了泛型在处理引用类型和值类型时的内存操作差异。此外,还讨论了泛型函数如何处理传入的函数,以及在不同场景下的行为特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

swift进阶总汇

本文主要介绍泛型及其底层原理

泛型

泛型主要用于解决代码的抽象能力 + 代码的复用性

例如下面的例子,其中的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{
    //在使用时,需要指定具体的类型
    
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值