我正在尝试为基于左边的协议实现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}}
有人知道如何解决这个问题吗?
答案 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}},以明确表示您正在进行身份比较,而不是进行价值比较:
===