Что такое протокол Comparable в Swift?

Ответ

Comparable — это протокол в Swift, который наследуется от Equatable и описывает типы, значения которых можно сравнивать с помощью операторов упорядочивания (<, <=, >, >=). Он является основой для стандартных операций сортировки, поиска минимума/максимума и работы с диапазонами.

Требования протокола: Для соответствия протоколу тип должен реализовать только оператор < (static func < (lhs: Self, rhs: Self) -> Bool). Компилятор Swift автоматически синтезирует реализации для остальных операторов сравнения (<=, >, >=) на основе < и == из Equatable.

Пример реализации для пользовательской структуры:

struct Person: Comparable {
    let name: String
    let age: Int
    // Требуемая реализация для Comparable
    static func < (lhs: Person, rhs: Person) -> Bool {
        return lhs.age < rhs.age
    }
    // Реализация для Equatable (синтезируется автоматически для структур, 
    // но можно задать свою)
    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.age == rhs.age && lhs.name == rhs.name
    }
}

let people = [Person(name: "Alice", age: 30), Person(name: "Bob", age: 25)]
let sortedByAge = people.sorted() // [Bob(25), Alice(30)]
let youngest = people.min() // Bob(25)

Ключевые принципы:

  • Реализация оператора < должна быть строгой, транзитивной и согласованной с ==.
  • Поскольку Comparable наследует Equatable, тип автоматически получает возможность проверки на равенство (==). Если все свойства соответствуют Equatable, реализацию == можно не писать — компилятор сгенерирует ее сам.

Ответ 18+ 🔞

А, Comparable, ёпта! Ну это ж та самая штука, которая заставляет наши типы встать в стройный ряд, как солдатики на параде, чтобы их можно было сравнивать — кто больше, кто меньше. По сути, это как дать компухтеру инструкцию: «Смотри, вот этот чувак старше, значит, он в очереди за пенсией будет впереди».

Протокол этот — сын протокола Equatable. То есть сначала ты говоришь «эти два объекта — однохуйственно одинаковые?» (это ==), а потом уже «а который из них левее/правее/выше/ниже?».

Самое офигенное правило, блядь:
Тебе, по идее, нужно реализовать всего один оператор — < (меньше). А компилятор, этот хитрожопый ублюдок, посмотрит на него, посмотрит на == от папаши Equatable, и САМ, сука, додумает, как должны работать >, <= и >=. Во какие дела, а? Лень — двигатель прогресса, ядрёна вошь!

Вот тебе живой пример, чтоб не быть пиздаболом:

struct Person: Comparable {
    let name: String
    let age: Int
    // ВОТ ОН, ГЛАВНЫЙ КАПИТАН ОЧЕРЕДИ! Говорим, что младше — тот и меньше.
    static func < (lhs: Person, rhs: Person) -> Bool {
        return lhs.age < rhs.age
    }
    // А это уже от Equatable. Можно и не писать, если все свойства сами по себе Equatable.
    // Компилятор за тебя сообразит. Но для ясности пусть будет.
    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.age == rhs.age && lhs.name == rhs.name
    }
}

let people = [Person(name: "Алиса", age: 30), Person(name: "Боб", age: 25)]
let sortedByAge = people.sorted() // [Боб(25), Алиса(30)] — молодёжь вперед!
let youngest = people.min() // Боб(25) — наш чемпион по юности!

Важные предупреждения, а то накосячишь:

  • Твой оператор < должен быть строгим. Нельзя, чтобы объект был меньше себя самого — это уже пиздец, шизофрения.
  • Он должен быть транзитивным. Если Вася младше Пети, а Петя младше Коли, то Вася и подавно младше Коли. Логика, блядь, а не высшая математика.
  • И он должен дружить с равенством (==). Если два объекта равны, то ни один из них не может быть меньше другого. Иначе комп начнёт ебаться в истерике.

Короче, реализовал < — и всё, ты король сортировок, поисков минимума и прочих радостей. Swift сам подхватит и сделает остальное, как хороший, но слегка заумный раб.