Урок 7. Условная конструкция switch

1 Ноября 2022

Что же такое условная конструкция switch, на самом деле она очень похожа на конструкцию if, только здесь синтаксис выглядит немного иначе. 

Давайте сперва рассмотрим пример с условной конструкцией if:

				
					let coin = "Gold"
var price = 0
				
			

У нас есть свойство coin, которое хранит в себе какую то монетку, это может быть золотая, монетка, может быть серебряная, либо медная. 

Представим приложение, в котором есть только текстовое поле, куда пользователь сам вносит значение для монеты. И вот наш вымышленный пользователь внес в текстовое поле значение Gold. Далее он жмет на кнопочку, и должно произойти какое то действие. В зависимости от того какая это монета, программа будет отображать на консоли ее  стоимость:

				
					let coin = "Gold"
var price = 0

if coin == "Gold" {
    price = 46220
} else if coin == "Silver" {
    price = 5500
} else {
    price = 498
}

print("\(coin) coin worth \(price) rubles")
				
			

Что мы тут делаем?! Мы берем значение coin и сравниваем с значениями, которые мы прописали в условиях, то есть мы сопоставляем их. И когда стоит задача именно сопоставить, то здесь лучше подойдет конструкция switch. Давайте сперва посмотрим на его синтаксис:

switch expression {

case value1:

    // код будет выполнен если expression == value1

case value2:

    // код будет выполнен если expression == value2

case value3:

    // код будет выполнен если expression == value3

default:

    // код будет выполнен если expression не равно не одному из value

}

 

Конструкция всегда начинается с ключевого слова switch, после которого мы определяем то значение, которое будем сравнивать. В нашем случае это свойство coin

Внутри конструкции, после ключевого слова case мы прописываем значения для сопоставления. в нашем случае это “Gold”, “Silver” и “Copper”, Кейсов может быть любое необходимое количество. После двоеточия определяем действие, которое должно случится, в том случае если сопоставляемое значение совпадет с кейсом. Если не один из кейсов не сработает, то будет выполнена дефолтная ветка. 

Наша конструкция будет выглядеть следующим образом:

				
					let coin = "Gold"
var price = 0

switch coin {
case "Gold":
    price = 46220
case "Silver":
    price = 5500
default:
    price = 498
}

print("\(coin) coin worth \(price) rubles")
				
			

по сути мы берем свойство coin и сравниваем по очередно с каждым кейсом coin == “Gold”.  Первый кейс нам подходит, поэтому на консоли мы увидим следующее сообщение:

Когда компилятор находит нужный кейс он дальше не будет делать проверку, он просто выйдет из конструкции. Давайте посмотрим как отрабатывает switch, если мы зададим для свойства coin значение “Copper”:

Мы видим что отработала дефолтная ветка, которая срабатывает в том случае если остальные кейсы не соответствуют сопоставляемому значению. 

Давайте пойдем путем компилятора, и проследим каждый его шаг. 

Сперва он видит два свойства coin и price и сохраняет их в памяти, затем он видит ключевое слово switch, понимает что нужно сопоставлять значения, берет значение, в нашем случае coin, и сравнивает  coin == “Gold”, в новой реализации, не равно, значит этот кейс он проходит мимо, и не реализует то что будет после двоеточия. Идет дальше и проверяет второй кейс coin == “Silver” – нет не равно, пропускает его. Все кейсы не прошли проверку на сопоставление, компилятору ничего не остается как выполнить дефолтную ветку, поэтому мы видим значение 498. 

То есть компилятор не уйдет из конструкции switch без результата, либо сработает какой то кейс, либо дефолтная ветка. 

После switch, мы всегда уходим с результатом, это исчерпывающая конструкция. 

Оператор break

Предположим, что в нашей конструкции switch мы решили определить в дефолтной ветке, следующий код:

				
					let coin = "Bronze"
var price = 0

switch coin {
case "Gold":
    price = 46220
case "Silver":
    price = 5500
case "Copper":
    price = 498
default:
    print("unknown coins")
}

print("\(coin) coin worth \(price) rubles")
				
			

В таком случае, если у нас будет какая то не известная монета, то отработает дефолтная ветка, и мы увидим два сообщения – принт с не известной монетой, и принт с типом монеты и ее нулевой ценой. 

Если вы пока не знаете что определить в дефолтной ветке, но она вам нужна что бы обработать дополнительные значения, то можете в ней просто прописать оператор break 

				
					switch coin {
case "Gold":
    price = 46220
case "Silver":
    price = 5500
case "Copper":
    price = 498
default:
    break  // Компилятор в этом месте просто выйдет из конструкции, и остановит все проверки. 
}
				
			

break вы можете определить в любом из кейсов, в этот момент компилятор просто выйдет из конструкции и никакие значения больше проверять не будет. 

Давайте представим, что нам ничего не нужно делать, если монета серебренная. В таком случае наша конструкция будет выглядеть следующим образом:

Компилятор проверил кейс с значением “Silver” и этот кейс подходит под наше сопоставляемое значение coin, соответсвенно реализуется код внутри кейса, после двоеточия, а там break, это команда компилятору, ничего не делать, просто выйти из конструкции switch, и пойти дальше. Поэтому на консоли мы видим только принт, с нулевым значением. 

Внутри кейса, либо в дефолтной ветки, после оператора break код не будет выполнятся.

Оператор where

Оператор where может использоваться в switch конструкции, когда следует указать дополнительное условие,  которое должно быть выполнено для сопоставления с кейсом. Давайте продолжим наш пример с монетами. 

Добавим условие при котором цена золотой монеты будет 46.220. Если у нашего пользователя есть клубная карта, то мы предложим ему эту цену, иначе сообщим, что у нас нет подходящего товара для него:

				
					let coin = "Gold"
let isCard = false
var price = 0

switch coin {
case "Gold" where isCard: // После where мы определяем логическое значение
    price = 46220
case "Silver":
    price = 5500
case "Сopper":
    price = 498
default:
    print("we have nothing to offer you")
}

if price > 0 {
    print("\(coin) coin worth \(price) rubles")
} // это условие нам нужно, в том случае если сработает дефолтная ветка, мы на консоли видели только один принт. 
				
			

мы сопоставляем значение coin с каждым кейсом. 

Компилятор проходит первый кейс и сравнивает значение из coin с значением кейса “Gold”, они равны, но этого не достаточно, компилятор видит оператор where и проверят какое логическое значение возвращается, isCard хранит в себе значение false, это говорит нам о том что кейс не будет выполнен. То есть должно совпадать и сопоставляемое значение и условное выражение после where должно вернуть true. 

В нашем случае первый кейс не будет выполнен, сработает дефолтная ветка. 

После оператора where так же могут быть и логические выражения, например мы будем давать за золотую монету такую стоимость, только если она номиналом 10 рублей:

				
					let coin = "Gold"
let denomination = 10
var price = 0

switch coin {
case "Gold" where denomination == 10:
    price = 46220
case "Silver":
    price = 5500
case "Сopper":
    price = 498
default:
    print("we have nothing to offer you")
}
				
			

В данном случае у нас сработает первый кейс, потому что у нас сопоставляемое значение совпадает с “Gold” и условное выражение после where возвращает true.

Объединение кейсов

Бывают случаи, когда вам необходимо выполнить одно и то же действие в двух разных кейсах, в этом случае их можно объединить в один, просто прописав кейсы через запятую.

Давайте рассмотрим пример

				
					let number = 2
var value = 0

switch number {
case 1:
    value += number
case 2:
    value -= number
case 3:
    value += number
case 4:
    value -= number
default:
    print("indefinitely")
}
				
			

Если у нас number равен 1 то сработает первый кейс и мы к свойству value будем прибавлять это значение, то же самое действие мы будем производить если number равен 3. Та же история со вторым и четвертым кейсом, действия повторяются. И это можно оптимизировать, просто прописав кейсы через запятую:

				
					let number = 2
var value = 0

switch number {
case 1, 3:
    value += number
case 2, 4:
    value -= number
default:
    print("indefinitely")
}
				
			

В данном случае запятая выступает оператором ИЛИ, то есть если number равен 1 или 3 то сработает первый кейс, если number равен 2 или 4 то сработает второй кейс. Во всех остальных случаях будет выполнена дефолтная ветка. 

Поддержите наш проект, и помогите изменить подход к обучению!

Развивайся вместе с нами

Поддержите наш проект, и помогите изменить подход к обучению!

Address List

Social Networks

Поддержите наш проект, и помогите изменить подход к обучению!