Chapters

Hide chapters

Swift Cookbook

Live Edition · Multiplatform · Swift · Editor agnostic

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.

© 2024 Kodeco Inc.