Chapter One swift basic: 2、协议 & 泛型

一、协议(Protocol)的核心内容

  1. 协议的基础

    • 定义协议:声明方法、属性、下标或初始化器的蓝图。
      protocol Drawable {
          func draw()
          var area: Double { get }
      }
      
    • 协议继承与组合
      • 继承:protocol Printable: Drawable { func print() }
      • 组合:typealias ClickablePrintable = Printable & Clickable
    • 协议扩展:为协议提供默认实现。
      extension Drawable {
          func draw() { print("Default drawing") }
      }
      
    • 可选协议要求:使用 @objc 标记,仅类可遵循。
      @objc protocol DataSource {
          @objc optional func numberOfRows() -> Int
      }
      
  2. 高级协议特性

    • 关联类型(Associated Types):协议中的占位类型,由遵循协议的类型指定。
      protocol Container {
          associatedtype Element
          mutating func append(_ item: Element)
          var count: Int { get }
      }
      
    • Self 关键字:表示遵循协议的具体类型。
      protocol Equatable {
          static func == (lhs: Self, rhs: Self) -> Bool
      }
      
  3. 协议作为类型

    • 变量、参数或返回值可声明为协议类型。
      func render(_ item: Drawable) {
          item.draw()
      }
      

二、泛型(Generics)的核心内容

  1. 泛型基础

    • 泛型函数:类型参数用 <T> 声明。
      func swap<T>(_ a: inout T, _ b: inout T) {
          let temp = a
          a = b
          b = temp
      }
      
    • 泛型类型:如自定义集合。
      struct Stack<Element> {
          var items: [Element] = []
          mutating func push(_ item: Element) { items.append(item) }
          mutating func pop() -> Element { items.removeLast() }
      }
      
  2. 类型约束

    • 限制泛型类型必须遵循协议或继承类。
      func findIndex<T: Equatable>(of value: T, in array: [T]) -> Int? {
          for (index, item) in array.enumerated() {
              if item == value { return index }
          }
          return nil
      }
      
  3. 泛型 Where 子句

    • 对关联类型或泛型参数进一步约束。
      func allEqual<T: Sequence>(_ sequence: T) -> Bool where T.Element: Equatable {
          // 检查所有元素是否相等
      }
      
  4. 条件遵循(Conditional Conformance)

    • 泛型类型在特定条件下遵循协议。
      extension Array: Equatable where Element: Equatable {
          // 自动实现数组的判等逻辑
      }
      

三、协议与泛型的结合

  1. 协议中的泛型:关联类型

    • 协议通过关联类型定义泛型行为。
      protocol Queue {
          associatedtype Element
          mutating func enqueue(_ element: Element)
          mutating func dequeue() -> Element?
      }
      
      struct IntQueue: Queue {
          typealias Element = Int // 可省略,编译器自动推断
          // 实现方法...
      }
      
  2. 类型擦除(Type Erasure)

    • 处理带有关联类型的协议,使其更易用。
      struct AnyQueue<Element>: Queue {
          private let _enqueue: (Element) -> Void
          private let _dequeue: () -> Element?
          
          init<Q: Queue>(_ queue: Q) where Q.Element == Element {
              _enqueue = queue.enqueue
              _dequeue = queue.dequeue
          }
          // 实现方法...
      }
      
  3. 不透明类型(Opaque Types)

    • 使用 some 关键字返回协议实例,隐藏具体类型。
      func makeQueue() -> some Queue {
          return IntQueue()
      }
      

四、需要掌握的内容总结

类别 核心知识点
协议 协议定义、继承、扩展、可选方法、关联类型、Self、协议作为类型
泛型 泛型函数/类型、类型约束、where子句、条件遵循、泛型与协议结合
高级应用 类型擦除、不透明类型、协议与泛型在集合/算法中的实际应用

五、面试常见问题与回答思路

  1. 协议与类有什么区别?

    • 回答:协议定义行为契约,无具体实现;类可继承、有状态。协议支持值类型和类,类仅支持引用类型。
  2. 关联类型的作用是什么?

    • 回答:允许协议声明占位类型,由遵循协议的具体类型指定,实现协议级别的泛型。
  3. 如何解决协议中关联类型的类型擦除问题?

    • 回答:通过类型擦除包装(如 AnySequence)或使用不透明类型(some Protocol)。
  4. 泛型 Where 子句的应用场景?

    • 回答:约束泛型参数或关联类型需满足额外条件,例如要求集合元素遵循 Equatable
  5. 设计一个支持多种数据类型的缓存系统,如何结合协议与泛型?

    • 回答
      protocol Cacheable {
          associatedtype Key: Hashable
          associatedtype Value
          func get(_ key: Key) -> Value?
          func set(_ key: Key, value: Value)
      }
      
      struct MemoryCache<K: Hashable, V>: Cacheable {
          private var storage: [K: V] = [:]
          func get(_ key: K) -> V? { storage[key] }
          func set(_ key: K, value: V) { storage[key] = value }
      }
      

六、实际应用场景

  • 网络层:使用协议定义请求,泛型解析响应。
    protocol APIRequest {
        associatedtype Response: Decodable
        var url: URL { get }
    }
    
    func fetch<T: APIRequest>(_ request: T) async throws -> T.Response {
        let data = try await downloadData(from: request.url)
        return try JSONDecoder().decode(T.Response.self, from: data)
    }
    
  • UI组件:泛型表格视图控制器,支持多种数据类型。
    class GenericTableViewController<T: CellDisplayable>: UITableViewController {
        var items: [T] = []
        // 根据 T 的类型动态配置单元格
    }
    

七、总结

  • 协议:定义行为规范,支持多态与代码复用。
  • 泛型:提升代码灵活性,避免类型重复。
  • 结合使用:通过关联类型和类型约束,实现高度抽象的通用逻辑。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。