You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift如何让包含协议类型属性的类型遵守Hashable/Equatable协议

最优实现方案:带Hashable能力的类型擦除器

核心解决思路是在类型擦除器中预存业务逻辑、相等判断、哈希逻辑三个闭包,既规避了协议作为属性类型无法携带Hashable约束的问题,也完全避免了你提到的两种方案的缺陷,扩展性极强。


步骤1:实现AnyFilterProcessor类型擦除器

protocol FilterProcessor {
    func satisfies(input: String) -> Bool
}

struct AnyFilterProcessor: FilterProcessor, Hashable {
    // 内部存储三类核心逻辑闭包
    private let _satisfies: (String) -> Bool
    private let _equals: (Any) -> Bool
    private let _hash: (inout Hasher) -> Void
    
    // 初始化约束:仅接受同时遵守FilterProcessor和Hashable的具体类型
    init<T: FilterProcessor & Hashable>(_ processor: T) {
        _satisfies = { processor.satisfies(input: $0) }
        _equals = {
            guard let other = $0 as? T else { return false }
            return processor == other
        }
        _hash = { hasher in
            processor.hash(into: &hasher)
        }
    }
    
    func satisfies(input: String) -> Bool {
        _satisfies(input)
    }
    
    static func == (lhs: AnyFilterProcessor, rhs: AnyFilterProcessor) -> Bool {
        lhs._equals(rhs)
    }
    
    func hash(into hasher: inout Hasher) {
        _hash(&hasher)
    }
}

该实现利用泛型初始化的特性,在构造擦除器时就把具体类型的Hashable/Equatable逻辑捕获进闭包,外部使用时完全感知不到具体类型,也不需要给FilterProcessor协议加关联类型约束。


步骤2:调整SelectionFilter实现

protocol Filter {
    associatedtype Input
    func satisfies(input: Input) -> Bool
}

struct SelectionFilter: Filter, Hashable {
    let identifier: String
    // 替换原协议类型为擦除器类型
    let processor: AnyFilterProcessor
    
    func satisfies(input: String) -> Bool {
        processor.satisfies(input: input)
    }
    
    // 两个属性都遵守Hashable,编译器会自动合成Equatable和Hashable实现,无需手动编码
}

步骤3:现有Processor仅需补充Hashable遵守即可

如果Processor是结构体,不需要手动写Hashable/Equatable实现,编译器会自动合成:

struct ProcessorOne: FilterProcessor, Hashable {
    let uuid: String
    let type: String
    func satisfies(input: String) -> Bool {
        // 原有业务逻辑无需修改
        return false
    }
}

struct ProcessorTwo: FilterProcessor, Hashable {
    let data: Int
    func satisfies(input: String) -> Bool {
        // 原有业务逻辑无需修改
        return false
    }
}

步骤4:集合代码仅需加一层擦除器包装即可正常运行

Set([
    SelectionFilter(identifier: "abc", processor: AnyFilterProcessor(ProcessorOne(uuid: "1234", type: "size"))),
    SelectionFilter(identifier: "def", processor: AnyFilterProcessor(ProcessorTwo(data: 1234)))
])

方案优势

  • 扩展性极强:新增Processor类型仅需遵守FilterProcessor & Hashable即可,不需要修改枚举、不需要继承基类,20+Processor也无额外维护成本
  • 安全性高:结构体类型的Processor编译器会自动生成Hashable/Equatable实现,不存在开发者漏写的问题
  • 无冗余代码:不需要针对每个Processor重复编写相等判断、哈希计算逻辑

内容的提问来源于stack exchange,提问作者tarun_sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 03:45:03