Conform to Equatable & Hashable in Swift
Written by Team Kodeco
When you define a custom class in Swift, you often want to provide a definition for equality and to allow the class to be used as a key in a Swift dictionary or set.
This can be done by conforming to two protocols in Swift: Equatable
and Hashable
. Let’s take a look.
Conform to Equatable
The Equatable
protocol in Swift is a protocol that requires any conforming type to implement the ==
operator, which is used to compare instances of the conforming type for equality.
By conforming to Equatable
, a type can provide its own implementation of equality, which may be different from the default implementation provided by the Swift standard library.
Here is the definition of the Equatable
protocol:
public protocol Equatable {
static func == (lhs: Self, rhs: Self) -> Bool
}
Here’s an example of how you can conform to the Equatable
protocol on a custom class:
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
extension Person: Equatable {
static func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name && lhs.age == rhs.age
}
}
let person1 = Person(name: "John", age: 30)
let person2 = Person(name: "John", age: 30)
let person3 = Person(name: "Jane", age: 25)
print(person1 == person2) // true
print(person1 == person3) // false
This example conforms to the Equatable protocol
by providing an implementation of the ==
operator. The function takes two instances of Person
as input and return a Boolean
based on the equality of their name
and age
properties.
Conform to Hashable
In addition to conforming to the Equatable
protocol, it’s also common practice to conform to the Hashable
protocol for classes that will be used as keys in a Dictionary
or as elements in a Set
.
Here is the definition of the Hashable
protocol:
public protocol Hashable: Equatable {
func hash(into hasher: inout Hasher)
var hashValue: Int { get }
}
The Hashable
protocol requires that any conforming type implement a hash(into:)
method, which is used to hash the properties of the instance into a Hasher
object. The protocol also requires the conforming type to have a read-only hashValue
property that returns an integer that represents the hash value of the instance.
Note that the Hashable
protocol inherits from Equatable
protocol, so any type conforming to Hashable
must also provide an implementation of the ==
operator.
Here’s an example of how you can conform to both Equatable
and Hashable
protocols on the Person
class:
class Person: Equatable, Hashable {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
static func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name && lhs.age == rhs.age
}
func hash(into hasher: inout Hasher) {
hasher.combine(name)
hasher.combine(age)
}
}
let john = Person(name: "John", age: 30)
let jane = Person(name: "Jane", age: 25)
let personDict = [john: "uno", jane: "dos"]
print(personDict[jane]!) // Output: "dos"
By conforming to the Hashable
protocol, you can now use the custom Person
class as keys in a Swift dictionary or set.