Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am trying to implement the Equatable protocol for a protocol based on the left' and right's operand identity. I other words: How do I implement the Equatable protocol for a protocol to determine if two instances that implement this protocol (in my case iNetworkSubscriber) are identical (same object reference). Like that (error message is include in the code below):

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)'
}

... and I also tried it with the identity operator itself:

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
}

Somebody an idea how to solve this issue?

like image 609
salocinx Avatar asked Jan 18 '18 15:01

salocinx


People also ask

How do you implement Equatable?

To adopt the Equatable protocol, implement the equal-to operator ( == ) as a static method of your type. The standard library provides an implementation for the not-equal-to operator ( != ) for any Equatable type, which calls the custom == function and negates its result.

What is the use of Equatable protocol in Swift?

In Swift, an Equatable is a protocol that allows two objects to be compared using the == operator. The hashValue is used to compare two instances. To use the hashValue , we first have to conform (associate) the type (struct, class, etc) to Hashable property.

Can a protocol conform to Equatable Swift?

Overview. Types that conform to the Equatable protocol can be compared for equality using the equal-to operator ( == ) or inequality using the not-equal-to operator ( != ). Most basic types in the Swift standard library conform to Equatable .

What is the difference between equitable and comparable protocol?

In Swift, there's the Equatable protocol, which explicitly defines the semantics of equality and inequality in a manner entirely separate from the question of identity. There's also the Comparable protocol, which builds on Equatable to refine inequality semantics to creating an ordering of values.


1 Answers

There are two problems here. The first is that you can't use ObjectIdentifier on value types. So you must declare this protocol to require reference (class) types:

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

(Please do not add a lowercase i to the beginning of protocols. This is confusing in several ways in Swift.)

Then, you cannot use this protocol as a type. It describes a type (because it relies on Self via Equatable). So functions that accept it must be generic.

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

Given that NetworkSubscriber must be a class, you should ask very carefully whether you should be using inheritance here rather than a protocol. Protocols with associated types are very complex to use, and mixing classes and protocols creates even more complexity. Class inheritance is much simpler if you're already using classes.

like image 66
Rob Napier Avatar answered Sep 28 '22 05:09

Rob Napier