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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 14:25:12