Ответ
Протокол Comparable наследуется от Equatable и позволяет определять порядок для экземпляров пользовательского типа с помощью операторов сравнения (<, <=, >, >=).
Основные сценарии использования:
- Сортировка коллекций. Методы
sorted(),sort()для массивов и других коллекций требуют, чтобы элементы былиComparable.let numbers = [5, 2, 8, 1] let sortedNumbers = numbers.sorted() // [1, 2, 5, 8] - Работа с алгоритмами и структурами данных, которые зависят от упорядочивания (например, бинарный поиск, нахождение минимума/максимума).
- Использование в условиях
if,guard,switch.if currentScore > highScore { highScore = currentScore } - Создание типов с естественным порядком (даты, версии, приоритеты).
Пример реализации для пользовательского типа:
struct Person: Comparable {
let name: String
let age: Int
// Требуется реализовать только оператор `<`.
// Остальные операторы (`<=`, `>`, `>=`) генерируются компилятором автоматически.
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)] Ответ 18+ 🔞
А, Comparable, ёпта! Ну это ж тот самый протокол, который из Equatable вылез, как глист из жопы, и позволяет тебе твои кастомные типы сравнивать операторами вроде < или >. Не просто "равно/не равно", а вот это вот всё — кто больше, кто меньше, кто впереди планеты всей.
Ну и зачем это вообще нужно, спросишь ты?
- Сортировка, мать её. Коллекции твои — массивы там всякие — хотят
sorted()илиsort()вызвать? А элементы-то Comparable должны быть, иначе получишь пиздюлину от компилятора. Без этого — никуда.let numbers = [5, 2, 8, 1] let sortedNumbers = numbers.sorted() // [1, 2, 5, 8] — вот так, по-порядку, как в армии. - Алгоритмы разные, структуры данных. Бинарный поиск, минимум/максимум найти — всё это ебётся об порядок. Без Comparable они просто пальцы веером.
- В условиях использовать. Ну,
if score > highScore— классика жанра, что тут объяснять. - Типы с естественным порядком сделать. Дата, версия программы, приоритет задачи — тут само собой напрашивается, что одно больше другого.
А вот смотри, как свою структуру научить сравниваться, на примере Person:
struct Person: Comparable {
let name: String
let age: Int
// Внимание, хуле! Реализовать нужно ТОЛЬКО оператор `<`.
// Всё остальное — `<=`, `>`, `>=` — компилятор сам сгенерит, умная жопа.
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)] — Боб моложе, вот он и впереди.
Вот и вся магия. Объявил протокол, один оператор написал — и пошло-поехало, сортируй, ищи, сравнивай. Главное — логику в < правильно засунуть, а то получится, что старик будет "меньше" юнца, и все твои алгоритмы накроются медным тазом.