Swift中any P类型无法使用!=运算符的原因及解决方法
问题分析与解决
错误原因
尽管协议P继承了Equatable,但any P是存在类型(existential type),它可以容纳任意遵循P协议的具体类型实例。而Equatable协议的==方法要求两个操作数必须是完全相同的Self类型,Swift无法在编译期确定两个any P实例的具体类型是否一致,也无法动态找到匹配的==实现,因此直接使用!=会触发编译错误。
解决方法
方法1:先校验类型再转换比较
先判断两个any P实例的具体类型是否一致,类型匹配后再转换为具体类型进行Equatable比较:
class T { var p: any P init(_ pp: any P) { self.p = pp } func update(_ pp: any P) { // 先判断类型是否相同 guard let concreteNewValue = pp as? type(of: p) else { p = pp return } // 类型相同后,直接用==比较 if concreteNewValue != p { p = pp } } }
方法2:给协议添加自定义比较方法
在P协议中定义一个专门用于存在类型比较的方法,利用默认实现自动适配Equatable逻辑:
protocol P: Equatable { func equals(_ other: any P) -> Bool } // 给P协议添加默认实现 extension P { func equals(_ other: any P) -> Bool { // 先尝试将other转换为当前类型,失败则直接返回false guard let concreteOther = other as? Self else { return false } // 类型匹配时调用Equatable的==方法 return self == concreteOther } } class T { var p: any P init(_ pp: any P) { self.p = pp } func update(_ pp: any P) { if !pp.equals(p) { p = pp } } }
方法3:将T改为泛型类(推荐,类型更安全)
如果可以确定T实例中存储的p始终是同一具体类型,将T改为泛型类,直接使用具体类型而非存在类型,这样Equatable可以正常工作:
class T<PType: P> { var p: PType init(_ pp: PType) { self.p = pp } func update(_ pp: PType) { if pp != p { p = pp } } }
内容的提问来源于stack exchange,提问作者John DoeDoe
相关产品推荐
相关产品推荐

