В Swift конструкции switch и enum реализованы с мощными возможностями сопоставления с образцом и строгой типобезопасностью, что отличает их от большинства аналогов в других языках.
В C и C++, а также в Objective-C, перечисления представляют собой просто набор целочисленных значений, а операторы switch сравнивают значения по совпадению. В Swift перечисления (enum) гораздо мощнее — поддерживают ассоциированные значения, вычисляемые свойства и методы. Оператор switch поддерживает сопоставление с образцом, защиту от неполных ветвлений и работу с range, tuple, optional и многим другим.
В традиционных языках switch часто приводит к ошибкам, связанным с отсутствием exhaustiveness (исчерпывающего рассмотрения всех кейсов), ошибкам типов и невозможности безопасно хранить дополнительные данные в кейсах enum. Это приводит к ошибкам на этапе выполнения, а не компиляции.
В Swift switch требует полной обработки всех случаев, если перечисление не явно помечено как @unknown default. Ассоциированные значения позволяют элегантно хранить дополнительную информацию в кейсах enum. Пример:
enum NetworkResult { case success(Int) case failure(String) } func handle(result: NetworkResult) { switch result { case .success(let code): print("Success with code: \(code)") case .failure(let error): print("Failure with error: \(error)") } }
Ключевые особенности:
Необходимо ли всегда писать default в switch по enum?
Нет, если все кейсы перечисления покрыты явно, default не нужен. Более того, default не рекомендуется использовать без необходимости — компилятор может не предупредить о новых кейсах enum при их добавлении.
Можно ли использовать fallthrough для автоматического перехода между кейсами?
Да, ключевое слово fallthrough доступно, но использовать его нужно аккуратно. Оно не передает ассоциированные значения, и такие переходы нечасто встречаются в реальной практике Swift.
switch number { case 1: print("one") fallthrough case 2: print("or two") default: print("other") }
Может ли enum в Swift быть сравнен по rawValue, если у него есть ассоциированные значения?
Нет. Только перечисления без ассоциированных значений и с явно указанным rawValue могут быть инициализированы и сравнены через rawValue.
Разработчик добавил default-case в switch по enum NetworkResult, что привело к тому, что при добавлении нового кейса логика обработки не обновилась, и программа "тихо" некорректно работала.
Плюсы: Нет предупреждений компилятора при добавлении кейсов.
Минусы: Ошибки проявляются во время работы приложения, логика не обновляется автоматически.
Сотрудник отказался от default в switch по enum, что позволило компилятору выявлять отсутствие обработки новых кейсов после их добавления.
Плюсы: Ошибки выявляются на этапе компиляции, поведение приложения становится более предсказуемым.
Минусы: При большом количестве кейсов требуется больше кода, но выигрываем в надежности.