如何让带any关键字的协议遵循Equatable协议?
Swift自定义协议遵循Equatable的常见问题解决
问题根源
你遇到的报错本质是Equatable协议依赖Self类型一致性,而any ExampleDataProtocol是经过类型擦除的存在类型,编译器无法保证两个any ExampleDataProtocol实例的具体类型相同,因此无法直接应用Equatable的比较逻辑。
你原代码里的两个问题:
- 结构体
SomeStruct无法自动合成Equatable实现:因为属性是存在类型,编译器不知道如何生成比较逻辑。 - 手动实现
==时直接比较any ExampleDataProtocol实例:存在类型本身不满足Equatable的Self类型要求,编译器拒绝执行比较。
另外你给协议扩展添加的static func ==(lhs: any ExampleDataProtocol, rhs: any ExampleDataProtocol)是多余的,Equatable协议只要求实现static func ==(lhs: Self, rhs: Self),这个any参数的方法不属于协议要求,反而会造成混淆。
解决方案
步骤1:修正协议定义与扩展
先去掉多余的any参数==方法,只保留符合Equatable要求的Self版本:
protocol ExampleDataProtocol: Equatable { var someData: Int { get set } } public extension ExampleDataProtocol { static func ==(lhs: Self, rhs: Self) -> Bool { return lhs.someData == rhs.someData } }
步骤2:手动实现结构体的Equatable逻辑
在结构体的==方法中,先判断两个any ExampleDataProtocol实例的具体类型是否一致,再强转后调用协议的比较方法:
struct SomeStruct: Equatable { var someData: any ExampleDataProtocol static func == (lhs: SomeStruct, rhs: SomeStruct) -> Bool { // 先检查两个实例的具体类型是否相同 guard let rhsMatchingType = rhs.someData as? type(of: lhs.someData) else { return false } // 类型一致后,调用协议的==方法比较 return lhs.someData == rhsMatchingType } }
补充说明
这种实现严格遵循Equatable的语义:只有当两个SomeStruct中的someData是同一具体类型,且属性值相等时,才判定两个SomeStruct实例相等。如果需要放宽类型要求(比如不同类型但someData值相同就判定相等),可以直接比较someData的属性值,但这不符合常规的Equatable语义,需要谨慎使用:
static func == (lhs: SomeStruct, rhs: SomeStruct) -> Bool { return lhs.someData.someData == rhs.someData.someData }
内容的提问来源于stack exchange,提问作者Mocha
相关产品推荐
相关产品推荐

