Jon Hoffman
Equatable Protocol: Protocol Oriented Design within Swift

When we want to find good examples of Protocol Oriented design in Swift, we do not have to look any further that the Swift language itself. One example that we wrote about earlier is using the IteratorProtocol and the Sequence protocols to enable us to traverse our custom data structures with the for..in.. loop. You can read about this in our Iterator Pattern: Protocol Oriented Design Pattern post. Another good example is the Equatable protocol that we will look at in this post.
The Equatable protocol enables us to compare two instances of a particular type, that adopts the Equatable protocol, using the == equal to operator or the != not equal to operator. We can use the Equatable protocol to enable comparison of our custom types because this capacity is defined in the type system, using protocols.
We will start off by looking at how we can adopt the Equatable with our custom types. Let’s say that we had the following structures:
struct Person {
var firstName: String
var lastName: String
var age: Int
}
In our code we would like to compare instances of this structure to see if they are the same person. In order to make this structure adopt the Equatable protocol all we need to do is to add the Equatable protocol to the structures definition like this:
struct Person: Equatable {
var firstName: String
var lastName: String
var age: Int
}
That is it, we are done. We can now compare instances of the Person structure like this:
var me = Person(firstName: "Jon", lastName: "Hoffman", age: 54)
var you = Person(firstName: "yourName", lastName: "lastname", age: 38)
var me2 = Person(firstName: "Jon", lastName: "Hoffman", age: 54)
print(me == you) //Prints false
print(me == me2) //Prints true
In the past example, all we needed to do was to add the Equatable protocol to the structures definition. As long as our type is a Structure or Enum, and all of the property types adopt the Equatable protocol, then that is all we have to do. However if our type is a Class, any of the property types doesn’t conform to the Equatable protocol or if we want to customize the comparison, then we need to write our own == function like this.
static func == (lhs: PersonClass, rhs: PersonClass) -> Bool {
return lhs.firstName == rhs.firstName &&
lhs.lastName == rhs.lastName &&
lhs.age == rhs.age
}
We can do this in the type itself or, as we prefer, in an extension like this:
extension Person: Equatable {
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.firstName == rhs.firstName &&
lhs.lastName == rhs.lastName &&
lhs.age == rhs.age
}
}
Being able to use equality operators like == and != simply by adopting the Equatable protocol shows how powerful a good protocol oriented design can be even if that was all we could do but there is more.
Swift uses the Equatable protocol in a number of places throughout the language itself. For example, in sequences we have a function called contains() which returns a Boolean value indicating whether the sequence contains a given element. Since the language needs to do a comparison of the elements in the sequence to the given element, in order to be able to use the function the elements type needs to conform to the Equatable protocol.
The functionality that we automatically gain by adopting a protocol such as the Equatable protocol is the results of a good protocol-oriented design within the Swift language itself. By having functionality tied to protocols, rather than types or functions, then any type that adopts a protocol will gain that functionality. We should keep this in mind when we are designing our own APIs, frameworks and applications.