如何根据实现该协议的两个实例的身份为协议实现 Equatable 协议?

How to implement Equatable protocol for a protocol based on the identity of two instances that implement this protocol?

我正在尝试为基于左右操作数标识的协议实现 Equatable 协议。换句话说:我如何为协议实现 Equatable 协议以确定实现该协议的两个实例(在我的例子中 iNetworkSubscriber)是否相同(相同的对象引用)。就像那样(错误消息包含在下面的代码中):

protocol iNetworkSubscriber : Equatable {

    func onMessage(_ packet: NetworkPacket)

}

func ==(lhs: iNetworkSubscriber, rhs: iNetworkSubscriber) -> Bool {     // <- Protocol 'iNetworkSubscriber' can only be used as a generic constraint because it has Self or associated type requirements
    return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)               // <- Cannot invoke initializer for type 'ObjectIdentifier' with an argument list of type '(iNetworkSubscriber)'
}

...我也尝试使用身份运算符本身:

func ==(lhs: iNetworkSubscriber, rhs: iNetworkSubscriber) -> Bool {     // <- Protocol 'iNetworkSubscriber' can only be used as a generic constraint because it has Self or associated type requirements
    return lhs === rhs                                                  // <- Binary operator '===' cannot be applied to two 'iNetworkSubscriber' operands
}

有人知道如何解决这个问题吗?

这里有两个问题。首先是您不能对值类型使用 ObjectIdentifier 。所以你必须声明这个协议需要引用(class)类型:

protocol NetworkSubscriber : class, Equatable {
    func onMessage(_ packet: NetworkPacket)
}

(请不要在协议的开头添加小写字母 i。这在 Swift 中的几个方面造成混淆。)

那么,您不能将此协议用作类型。它描述了一种类型(因为它通过 Equatable 依赖于 Self)。所以接受它的函数必须是通用的。

func ==<T: NetworkSubscriber>(lhs: T, rhs: T) -> Bool {
    return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
}

鉴于 NetworkSubscriber 必须是 class,您应该非常仔细地询问是否应该在此处使用继承而不是协议。具有关联类型的协议使用起来非常复杂,混合 classes 和协议会产生更多的复杂性。 Class 如果您已经在使用 classes,那么继承会简单得多。

身份比较只对对象有意义(类、class 协议的实例)。所以马上,您知道您需要对协议进行 class 约束:

protocol NetworkSubscriber: class, Equatable {
    func onMessage(_ packet: NetworkPacket)
}

执行此操作后,身份比较运算符 === 可用于 NetworkSubscriber 的实例(因为它们现在保证是对象)。我建议您直接使用 ===,而不是定义调用 =====,以明确表示您正在执行身份比较,而不是值比较:

let ns1 = getNewNetworkSubscriber()
let ns2 = getNewNetworkSubscriber()
print(n1 === n2) // false
print(n1 === n1) // true