如何基于实现此协议的两个实例的身份为协议实现Equatable协议?

时间:2018-01-18 15:10:16

标签: ios swift protocols swift4 equatable

我正在尝试为基于左边的协议实现Equatable协议。和正确的操作权身份。换句话说:我如何为协议实现Equatable协议,以确定实现此协议的两个实例(在我的情况下为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
}

...我也尝试过身份运营商本身:

{{1}}

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

2 个答案:

答案 0 :(得分:3)

这里有两个问题。首先,您不能在值类型上使用ObjectIdentifier。因此,您必须声明此协议需要引用(类)类型:

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

(请不要在协议开头添加小写i。这在Swift中有多种方式令人困惑。)

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

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

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

答案 1 :(得分:2)

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

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

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

===