Какие знаешь виды Enum?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Виды Enum в Swift
В Swift перечисления (Enum) — это мощная и многофункциональная конструкция, которая эволюционировала далеко за пределы простых списков значений. Они обеспечивают типобезопасность, могут иметь связанные значения, методы, свойства и соответствовать протоколам. Вот основные виды enum, которые я использую в разработке.
1. Базовые (Case) Enums
Это классические перечисления, представляющие собой набор простых связанных случаев. Они являются типами первого класса и по умолчанию типобезопасны.
enum CompassDirection {
case north
case south
case east
case west
}
let direction: CompassDirection = .north
switch direction {
case .north:
print("Heading north")
default:
break
}
2. Enums с Raw Values (сырыми значениями)
Каждому кейсу предопределяется значение базового типа (String, Character, Int, Float). Для Int значения могут быть автоматически инкрементными, для String — равными имени кейса.
enum Planet: Int {
case mercury = 1, venus, earth, mars // venus будет 2, earth — 3
}
enum HTTPStatus: String {
case success = "200 OK"
case notFound = "404 Not Found"
}
let earth = Planet.earth
print(earth.rawValue) // Вывод: 3
3. Enums с Associated Values (ассоциированными значениями)
Пожалуй, самая мощная особенность enum в Swift. Позволяет хранить дополнительные данные разного типа вместе с кейсом. Это ключевое отличие от raw values, где значение одно для всех экземпляров кейса.
enum Barcode {
case upc(Int, Int, Int, Int) // Ассоциированные значения типа Int
case qrCode(String) // Ассоциированное значение типа String
}
let productCode = Barcode.upc(8, 85909, 51226, 3)
switch productCode {
case .upc(let numberSystem, let manufacturer, let product, let check):
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check)")
case .qrCode(let codeString):
print("QR: \(codeString)")
}
Использование таких enum отлично подходит для моделирования вариантов результата (например, успех/ошибка с данными) или дискриминантных объединений.
4. Рекурсивные Enums (Indirect)
Позволяют кейсу иметь ассоциированное значение, которое является тем же типом enum. Требуют указания ключевого слова indirect — либо для всего enum, либо для конкретного кейса. Классический пример — моделирование арифметического выражения или связного списка.
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}
let expr = ArithmeticExpression.addition(
.number(5),
.multiplication(.number(2), .number(3))
)
5. Enums с методами и вычисляемыми свойствами
Перечисления могут содержать методы (как экземплярные, так и статические) и вычисляемые свойства, что делает их по-настоящему полноценными типами.
enum TrafficLight {
case red, yellow, green
var description: String { // Вычисляемое свойство
switch self {
case .red: return "Stop"
case .yellow: return "Wait"
case .green: return "Go"
}
}
mutating func next() { // Мутирующий метод
switch self {
case .red: self = .green
case .yellow: self = .red
case .green: self = .yellow
}
}
}
var light = TrafficLight.red
print(light.description) // "Stop"
light.next()
print(light) // green
6. Enums, соответствующие протоколам
Enum может соответствовать одному или нескольким протоколам, например, CaseIterable для автоматического получения массива всех кейсов, CustomStringConvertible для кастомного описания.
enum GameState: CaseIterable, Equatable {
case menu, playing, paused, gameOver
}
for state in GameState.allCases {
print(state)
}
// Будет выведено: menu, playing, paused, gameOver
Ключевые различия и когда что использовать:
- Raw Values vs Associated Values: Используйте Raw Values, когда каждому кейсу нужно присвоить уникальное, предопределённое постоянное значение (статусы, коды). Используйте Associated Values, когда кейс должен нести различную дополнительную информацию, которая может меняться от экземпляра к экземпляру (сетевой ответ, событие UI).
- CaseIterable: Незаменим для автоматической генерации списка всех кейсов, что полезно для тестов, UI-пикеров или конфигураций.
- Рекурсивные enum: Специфичны, но идеальны для моделирования древовидных или иерархических структур данных прямо в системе типов.
Таким образом, enum в Swift — это не просто список констант, а мощный инструмент для моделирования предметной области с гарантиями компилятора. Правильное использование разных видов enum (особенно с ассоциированными значениями) позволяет создавать выразительный, безопасный и легко поддерживаемый код, избегая сложных иерархий классов или небезопасных конструкций вроде строковых констант.