Какие требования должен выполнить класс, чтобы его можно было использовать как ключ в Dictionary?

«Какие требования должен выполнить класс, чтобы его можно было использовать как ключ в Dictionary?» — вопрос из категории Swift Core, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Чтобы класс можно было использовать как ключ в Dictionary, он должен соответствовать протоколу Hashable (который, в свою очередь, наследует протокол Equatable).

Требования:

  1. Реализовать Equatable: Определить оператор == для сравнения двух экземпляров на равенство.
  2. Реализовать Hashable: Реализовать метод hash(into:), который передаёт все значимые для равенства свойства в предоставленный Hasher.

Ключевое правило: Если два экземпляра равны согласно ==, то их хеш-значения, сгенерированные hash(into:), должны быть одинаковыми. Обратное не обязательно — разные объекты могут иметь одинаковый хеш (коллизия), но это снижает производительность словаря.

class User: Hashable {
    let id: UUID
    let username: String

    init(id: UUID, username: String) {
        self.id = id
        self.username = username
    }

    // 1. Реализация Equatable
    static func == (lhs: User, rhs: User) -> Bool {
        // Для равенства пользователей достаточно сравнить их уникальный id
        return lhs.id == rhs.id
    }

    // 2. Реализация Hashable
    func hash(into hasher: inout Hasher) {
        // В хеширование включаем только свойства, используемые в `==`
        hasher.combine(id)
    }
}

// Теперь класс User можно использовать как ключ
var scores: [User: Int] = [:
let user = User(id: UUID(), username: "Alice")
scores[user] = 100