Какие особенности есть у enum в Swift, включая ассоциативные значения, raw значения и рекурсивные enum
Что проверяют
Понимаете ли вы, что перечисление в Swift это полноценный тип-сумма, а не просто набор констант.
Как отвечать
Перечисление описывает один из нескольких взаимоисключающих случаев. В Swift оно заметно мощнее, чем в большинстве языков.
Ассоциативные значения: каждый случай может нести свои данные разного типа. Это и делает перечисление типом-суммой:
enum LoadState {
case idle
case loading(progress: Double)
case success([Job])
case failure(Error)
}Компилятор проверяет switch на полноту: добавили случай, и все обработчики без него перестают компилироваться. Именно поэтому состояние экрана моделируют перечислением, а не набором из четырёх независимых булевых полей, где возможны невозможные комбинации.
Raw-значения: если случаи сопоставлены с примитивами (enum Status: String), появляется rawValue и отказной инициализатор init?(rawValue:). Отсюда удобный разбор строк из API и автоматическая поддержка Codable. Важно: ассоциативные и raw-значения взаимоисключающи, вместе их использовать нельзя.
Рекурсивные перечисления: случай ссылается на само перечисление, для чего нужен indirect, потому что размер иначе нельзя вычислить. Так описывают деревья и выражения:
indirect enum Expr { case value(Int), sum(Expr, Expr) }Ещё стоит назвать: у перечислений бывают методы, вычисляемые свойства и расширения; CaseIterable даёт allCases; перечисление это значимый тип.
Где спотыкаются
Пишут default в switch и теряют проверку полноты при добавлении случая.
Пытаются совместить raw-значения с ассоциативными.
Не знают про indirect и не могут описать рекурсивную структуру.
Моделируют состояние набором булевых флагов вместо перечисления.