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
相关产品推荐
相关产品推荐

