Оператор swich позволяет проверить определенное значение и сравнить его с несколькими условиями. Это особенно эффективно для принятия решений на основе переменной, которая может содержать ряд возможных значений. Использование оператора switch позволяет использовать более краткий и удобный синтаксис кода.
Что из себя представляет оператор switch?
Оператор switch проверяет значение и сравнивает его с несколькими возможными шаблонами.
Рассмотрим следующее перечисление:
enum Compass { case north case east case south case west }
Если вы хотите найти нужное направление, вы можете использовать следующий код:
let heading = Compass.south if heading == .north { print("Вы направляетесь на север!") } else if heading == .east { print("Вы направляетесь на восток!") } else if heading == .south { print("Вы направляетесь на юг!") } else if heading == .west { print("Вы направляетесь на запад!") }
Приведенный выше код использует оператор if для оценки значения heading и вывода соответствующей строки текста.
Мы можем сделать то же самое, используя оператор switch:
switch heading { case .north: print("Вы направляетесь на север!") case .east: print("Вы направляетесь на восток!") case .south: print("Вы направляетесь на юг!") case .west: print("Вы направляетесь на запад!") }
Сначала мы используем ключевое слово switch, а затем проверяемое выражение, в данном случае это константа heading. Это значение, которое рассматривается блоками switch. Затем мы перебираем возможные варианты значений с помощью case. В приведенном выше примере мы рассматриваем все возможные значения перечисления Compass.
Особенностью switch является то, что каждый switch блок должен быть исчерпывающим. Посмотрите, что происходит, когда мы забываем включить вариант с .east:
switch heading { case .north: print("Вы направляетесь на север!") case .south: print("Вы направляетесь на юг!") case .west: print("Вы направляетесь на запад!") } // error: switch must be exhaustive
Особенности работы с оператором switch
Даже если заявление со switch должно быть исчерпывающим, вам не нужно явно указывать каждый параметр.
Рассмотрим перечисление Authorization:
enum Authorization { case granted case undetermined case unauthorized case denied case restricted }
Если вы хотите предоставить пользователю доступ к ресурсу в зависимости от его состояния авторизации, вы можете сделать это:
switch state { case .granted: print("Доступ разрешен.") default: print("Доступ закрыт!") }
В приведенном выше коде парамтер default используется для ответа на любой необработанный случай. Это делает выражение со switch исчерпывающим.
Вы также можете проверить более сложные случаи:
switch state { case .granted: print("Доступ разрешен.") case .undetermined: print("Предоставьте код доступа.") case .unauthorized, .denied, .restricted: print("Доступ закрыт!") }
Последний случай объединяет несколько случаев в одной строке.
Для того, чтобы было выполнено несколько условий, вы можете использовать оператор fallthrough:
var message = "Ответ: " let state = Authorization.undetermined switch state { case .granted: message += "Доступ открыт. Вы можете продолжить" case .undetermined: message += "Предоставьте код доступа." fallthrough default: message += "Доступ закрыт!" } print(message) // Output: Ответ: Предоставьте код доступа. Доступ закрыт!
В приведенном выше примере выполняется как условие .undetermined, так и default.
Проверка диапазонов с помощью switch
Вы можете использовать операторы switch для проверки интервалов и диапазонов.
Рассмотрим, например, как люди воспринимают видимый свет с разными длинами волн:
let wavelength = 620 switch wavelength { case 380..<450: print("Пурпурный!") case 450..<495: print("Синий!") case 495..<570: print("Зеленый!") case 570..<590: print("Желтый!") case 590..<620: print("Оранжевый!") case 620..<750: print("Красный!") default: print("Не видимый спектр!") }
Для каждого диапазона длины волны мы определяем интервал с оператором полуоткрытого диапазона.
Оператор switch и кортежи
Вы можете использовать оператор switch с кортежами.
Кортеж представляет собой упорядоченный список из двух или более значений. Например:
let flight = (747, "SFO")
Тип константы flight (Int, String). После определения кортежа вы не можете изменить его порядок или тип. Кортежи идеально подходят для передачи нескольких связанных значений в одну переменную.
Вы можете получить доступ к значениям кортежа с помощью индекса:
print(flight.1) // Output: SFO
Также можно использовать значения кортежа:
let flight = (airplane: 747, airport: "SFO") print(flgith.airplane) // Output: 747
Мы можем использовать кортежи вместе с оператором switch:
for i in 1...100 { switch (i % 3 == 0, i % 5 == 0) { case (true, false): print("Fizz") case (false, true): print("Buzz") case (true, true): print("FizzBuzz") default: print(i) } }
В приведенном выше коде мы создаем кортеж из двух значений: результат вычисления i % 3 == 0 и результат вычисления i % 5 == 0. Теперь мы можем учитывать различные значения кортежей: (true, false), (false, true), (true, true). Если ни один из этих случаев не совпадает, мы выводим значение i.
Поскольку мы используем switch для проверки значений кортежа, мы также можем проверять различные совпадающие значения в кортеже:
let airplane = (type: "737-800", heading: "LAX") switch airplane { case ("737-800", _): print("Этот самолет модели 737-800.") case (let type, "LAX"): print("Этот \(type) летит в аэропорт Лос-Анджелеса.") default: print("Неизвестный самолет.") } // Этот самолет модели 737-800.
В приведенном выше коде мы отвечаем 3 разных случая.
Выражение let type называется связыванием значения. Это позволяет нам привязать значение кортежа к константе. Теперь внутри case блока вы можете использовать эту константу, например, распечатать ее.
Использование switch с where
Мы также можем использовать switch с оператором where:
enum Response { case error(Int, String) case success } let httpResponse = Response.success switch httpResponse { case .error(let code, let status) where code > 399: print("HTTP Ошибка: \(code) \(status)") case .error: print("HTTP запрос неуспешен") case .success: print("HTTP запрос успешен") } // HTTP запрос успешен
В приведенном коде происходят две вещи:
- Мы создаем перечисление Response, которое имеет два случая: .error и .success. Случай .error имеет два соответствующие значения: целое число и строку.
- Мы оцениваем значение httpResponse с помощью оператора switch, реагируя на разные значения перечисления Response.
Если мы изменим значение httpResponse:
let httpResponse = Response.error(404, "Not Found") // HTTP Ошибка: 404 Not Found
Или:
let httpResponse = Response.error(301, "Moved Permanently") // HTTP запрос неуспешен
Есть еще один .error случай, который нас особенно интересует, а именно код ошибки, который больше, чем 399.
Коды состояния HTTP, которые используются в интернете, указывают на то, что коды состояния от 400 и выше являются ошибками клиента и сервера. Иными словами, когда вы получаете один из них, что-то пошло не так.
В приведенном выше коде мы используем привязку значений для констант code и status соответствующих значений перечисления Response. Мы также используем ключевое слово where, чтобы указать, что этот случай должен выполняться для любого значения code, превышающего 399.
В тексте опечатка в слове параметр-
В приведенном выше коде парамтер default используется для ответа на любой необработанный случай. Это делает выражение со switch исчерпывающим.