Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Protocol Implements Equatable

I have the the below Protocol:

protocol Cacheable {     //....//     func identifier() -> String } 

Can I make Cacheable implements Equatable ?

when I do the following:

extension Cacheable: Equatable {}  func ==(lhs:Cacheable,rhs:Cacheable) -> Bool {       return lhs.identifier() == rhs.identifier() } 

I got this error message : Extension of protocol Cacheable cannot have an inheritance clause

like image 753
Bobj-C Avatar asked Aug 10 '15 14:08

Bobj-C


People also ask

How do you conform to Equatable protocol?

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 ( != ).

Are arrays Equatable Swift?

Swift 4.1 update: With the introduction of conditional conformance in Swift 4.1, Array now conforms to Equatable , so the issue should be resolved without the need to resort to any workarounds.

Is void Equatable Swift?

Since Swift. Void is not Equatable , Box<Void> is not Equatable .

Is hashable Equatable?

It is another protocol that is inherited from equatable, by conforming to which you will get a hash value of integer type for a particular instance, any type that conforms to Hashable must also conform to Equatable.


2 Answers

1) Allow two Cacheables of the same type to be compare

protocol Cacheable: Equatable {     //....//     func identifier() -> String }  func ==<T : Cacheable>(lhs: T, rhs: T) -> Bool {     return lhs.identifier() == rhs.identifier() } 

Pros

This is the simplest solution.

Cons

You can only compare two Cacheable objects of the same type. This means that code below will fail and in order to fix it you need to make Animal conform to Cacheable:

class Animal {  }  class Dog: Animal,Cacheable {     func identifier() -> String {         return "object"     } }  class Cat: Animal,Cacheable {     func identifier() -> String {         return "object"     } }  let a = Dog()  let b = Cat()  a == b //such comparison is not allowed 

2) Allow Cacheables of any type to be compared

protocol Cacheable:Equatable {     //....//     func identifier() -> String }  func ==<T:Cacheable>(lhs: T, rhs: T) -> Bool {     return lhs.identifier() == rhs.identifier() }  func !=<T:Cacheable>(lhs: T, rhs: T) -> Bool {     return lhs.identifier() != rhs.identifier() }  func ==<T:Cacheable, U:Cacheable>(lhs: T, rhs: U) -> Bool {     return lhs.identifier() == rhs.identifier() }  func !=<T:Cacheable, U:Cacheable>(lhs: T, rhs: U) -> Bool {     return lhs.identifier() != rhs.identifier() } 

Pros

Removes limitations described above for solution 1. Now you can easily compare Dog and Cat.

Cons

  • Implementation is longer. Actually I am not sure why specifying only == functions is not sufficient - this might be a bug with a compiler. Anyway, you have to provide the implementation for both == and !=.
  • In some cases the benefit of this implementation may also pose a problem as you are allowing the comparison between absolutely different objects and compiler is totally OK with it.

3) Without conforming to Equatable

protocol Cacheable {     //....//     func identifier() -> String }  func ==(lhs: Cacheable, rhs: Cacheable) -> Bool {     return lhs.identifier() == rhs.identifier() }  func !=(lhs: Cacheable, rhs: Cacheable) -> Bool {     return lhs.identifier() != rhs.identifier() } 

Pros

You can use Cacheable as type without needing any generics. This introduces a whole new range of possibilities. For example:

let c:[Cacheable] = [Dog(),RaceCar()]  c[0] == c[1] c[0] != c[1] 

With solutions 1 and 2 such code would fail and you would have to use generics in your classes. However, with the latest implementation Cacheable is treated as a type, so you are allowed to declare an array of type [Cacheable].

Cons

You no longer declare conformance to Equatable so any functions which accept Equatable parameters will not accept Cacheable. Obviously, apart from == and != as we declared them for Cacheables.

If this is not a problem in your code I would actually prefer this solution. Being able to treat protocol as a type is super useful in many cases.

like image 150
Andriy Gordiychuk Avatar answered Oct 06 '22 05:10

Andriy Gordiychuk


Try.

extension Equatable where Self : Cacheable { } 
like image 25
Juri Noga Avatar answered Oct 06 '22 03:10

Juri Noga