Ответ
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 сам подхватит и сделает остальное, как хороший, но слегка заумный раб.