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

SE-0309能否解决Swift中协议作为Set元素无法遵循Hashable的问题

结论

SE-0309无法完全解决你遇到的问题,仅能解除部分旧版本的语法限制。

错误原因说明

  • 你定义的Set<MyStuff>中,MyStuff作为协议类型(存在类型)本身并不遵循Hashable协议。即便你为所有遵循MyStuff的类型扩展实现了Hashable要求,这份实现也仅作用于具体的实现类型(比如示例中的Stuff结构体),不会作用于协议本身。
  • SE-0309的作用是取消了「带Self或关联类型要求的协议不能直接作为类型使用」的旧版本限制,在Swift 5.7及以上版本中,你可以用any MyStuff明确声明存在类型,不会再报旧的约束限制错误,但该提案没有实现「协议存在类型自动遵循自身继承的协议」的能力,因此哪怕你修改为Set<any MyStuff>,编译器依然会提示协议无法遵循Hashable的错误。

可用解决方案

方案1:使用泛型约束替代存在类型

如果你的业务场景允许,在所有用到该集合的位置声明泛型参数T: MyStuff,使用Set<T>作为集合类型,让编译器在编译期确定具体的元素类型即可正常使用。

方案2:手动实现类型擦除包装器

如果确实需要存储不同遵循MyStuff协议的类型到同一个集合中,可以手动实现一个类型擦除包装器,示例代码如下:

struct AnyMyStuff: MyStuff, Hashable {
    private let wrappedValue: any MyStuff
    var stuff: String { wrappedValue.stuff }
    
    init<T: MyStuff>(_ value: T) {
        wrappedValue = value
    }
}

// 使用示例
let set: Set<AnyMyStuff> = [AnyMyStuff(Stuff(stuff: "Stuff"))]

由于你已经在MyStuff的扩展中实现了Hashable的默认逻辑,编译器会自动为AnyMyStuff合成符合要求的Hashable实现,不需要额外手动编写。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 19:12:01