Swift — Основные операторы
Оператор является специальным символом или фразы , которую вы используете , чтобы проверить, изменить или скомбинировать значение. Например, оператор сложения ( + ) добавляет два числа, как в , а логический оператор И ( ) объединяет два логических значения, как в . let i = 1 + 2 && if enteredDoorCode && passedRetinaScan
Swift поддерживает большинство стандартных операторов C и улучшает некоторые возможности для устранения распространенных ошибок кодирования. Оператор присваивания ( = ) не возвращает значение, чтобы предотвратить его ошибочное использование, когда == предполагается, что равно operator ( ). Арифметические операторы ( + , — , * , / , % и т.д.) обнаружить и запретить переполнение значения, чтобы избежать неожиданных результатов при работе с числами , которые становятся больше или меньше , чем диапазон допустимого значения типа , который хранит их. Вы можете выбрать поведение переполнения, используя операторы переполнения Swift, как описано в разделе «Операторы переполнения» .
Swift также предоставляет операторы диапазона, которых нет в C, такие как a..
В этой главе описываются общие операторы в Swift. Расширенные операторыохватывают расширенные операторы Swift и описывают, как определять свои собственные пользовательские операторы и реализовывать стандартные операторы для собственных пользовательских типов.
Терминология
Операторы унарные, двоичные или троичные:
- Унарные операторы работают на одну цель (например, -a ). Унарные префиксныеоператоры появляются непосредственно перед их целью (например !b ), а унарные постфиксные операторы появляются сразу после их цели (например c! ).
- Бинарные операторы работают с двумя целями (такими как ) и являются инфиксными, потому что они появляются между двумя целями. 2 + 3
- Тернарные операторы работают на три цели. Как и C, Swift имеет только один троичный оператор — троичный условный оператор ( ). a ? b : c
Значения, на которые влияют операторы, являются операндами . В выражении , то символ является бинарным оператором и его два операнда являются значениями и . 1 + 2 + 1 2
Оператор присваивания
Оператор присваивания ( ) инициализирует или обновляет значение со значением : a = b a b
let b = 10 var a = 5 a = b // a is now equal to 10
Если правая часть присваивания представляет собой кортеж с несколькими значениями, его элементы можно разложить на несколько констант или переменных одновременно:
let (x, y) = (1, 2) // x is equal to 1, and y is equal to 2
В отличие от оператора присваивания в C и Objective-C, оператор присваивания в Swift сам по себе не возвращает значение. Следующее утверждение недопустимо:
if x = y < // This is not valid, because x = y does not return a value. >
Эта функция предотвращает = случайное использование оператора присваивания ( ), когда == фактически предполагается равенство с оператором ( ). Делая недействительным, Swift помогает вам избежать подобных ошибок в вашем коде. if x = y
Арифметические операторы
Swift поддерживает четыре стандартных арифметических оператора для всех типов чисел:
- Дополнение ( + )
- Вычитание ( — )
- Умножение ( * )
- Отдел ( / )
1 + 2 // equals 3 5 - 3 // equals 2 2 * 3 // equals 6 10.0 / 2.5 // equals 4.0
В отличие от арифметических операторов в C и Objective-C, арифметические операторы Swift не допускают переполнения значений по умолчанию. Вы можете выбрать поведение переполнения, используя операторы переполнения Swift (например, ). Смотрите Операторы переполнения . a &+ b
Оператор сложения также поддерживается для String объединения:
"hello, " + "world" // equals "hello, world"
Оставшийся оператор
Оператор remainder ( ) определяет, сколько крат будет помещаться внутри, и возвращает оставшееся значение (известное как остаток ). a % b b a
ЗАМЕТКА
Оператор остатка ( % ) также известен как оператор по модулю в других языках. Однако его поведение в Swift для отрицательных чисел означает, что, строго говоря, это остаток, а не операция по модулю.
Вот как работает оператор остатка. Чтобы рассчитать , вы сначала определите, сколько s поместится внутри : 9 % 4 4 9
Вы можете поместить два 4 s внутри 9 , а остальное 1 (показано оранжевым цветом).
В Swift это будет записано как:
9 % 4 // equals 1
Чтобы определить ответ для , оператор вычисляет следующее уравнение и возвращает его результат: a % b % remainder
a = ( b х ) + some multiplier remainder
где наибольшее число, кратное тому, что поместится внутри . some multiplier b a
Вставка 9 и 4 в это уравнение дает:
Тот же метод применяется при расчете остатка для отрицательного значения a :
-9 % 4 // equals -1
Вставка -9 и 4 в уравнение дает:
давая остаток стоимости -1 .
Знак b игнорируется для отрицательных значений b . Это значит, что и всегда дают один и тот же ответ. a % b a % -b
Унарный минус оператор
Знак числового значения можно переключать с помощью префикса — , известного как унарный оператор минус :
let three = 3 let minusThree = -three // minusThree equals -3 let plusThree = -minusThree // plusThree equals 3, or "minus minus three"
Оператор унарного минуса ( — ) добавляется непосредственно перед значением, с которым он работает, без пробелов.
Унар Плюс Оператор
Унарный плюс ( + ) просто возвращает значение, которое действует на, без каких — либо изменений:
let minusSix = -6 let alsoMinusSix = +minusSix // alsoMinusSix equals -6
Хотя унарный оператор плюс на самом деле ничего не делает, вы можете использовать его, чтобы обеспечить симметрию в своем коде для положительных чисел, а также использовать унарный оператор минус для отрицательных чисел.
Составные операторы присваивания
Как и C, Swift предоставляет составные операторы присваивания, которые комбинируют метод assign ( = ) с другой операцией. Одним из примеров является оператор присваивания ( += ):
var a = 1 a += 2 // a is now equal to 3
Выражение является сокращением для . По сути, сложение и назначение объединяются в одного оператора, который выполняет обе задачи одновременно. a += 2 a = a + 2
ЗАМЕТКА
Составные операторы присваивания не возвращают значение. Например, вы не можете писать . let b = a += 2
Для получения информации об операторах, предоставляемых стандартной библиотекой Swift, см. Объявления операторов .
Операторы сравнения
Swift поддерживает все стандартные операторы сравнения C :
- Равно ( ) a == b
- Не равно ( ) a != b
- Больше чем ( ) a > b
- Меньше чем ( ) a < b
- Больше или равно ( ) a >= b
- Меньше или равно ( ) a
ЗАМЕТКА
Swift также предоставляет два идентификатора оператора ( === и !== ), которые вы используете, чтобы проверить, ссылаются ли обе ссылки на один и тот же экземпляр объекта. Для получения дополнительной информации см. Identity Operators .
Каждый из операторов сравнения возвращает Bool значение, чтобы указать, верно ли утверждение:
1 == 1 // true because 1 is equal to 1 2 != 1 // true because 2 is not equal to 1 2 > 1 // true because 2 is greater than 1 1 < 2 // true because 1 is less than 2 1 >= 1 // true because 1 is greater than or equal to 1 2
Операторы сравнения часто используются в условных выражениях, таких как if :
let name = "world" if name == "world" < print("hello, world") >else < print("I'm sorry \(name), but I don't recognize you") >// Prints "hello, world", because name is indeed equal to "world".
Для получения дополнительной информации об if операторе см. Поток управления .
Вы можете сравнить два кортежа, если они имеют одинаковый тип и одинаковое количество значений. Кортежи сравниваются слева направо, по одному значению за раз, пока сравнение не обнаружит два значения, которые не равны. Эти два значения сравниваются, и результат этого сравнения определяет общий результат сравнения кортежей. Если все элементы равны, то сами кортежи равны. Например:
(1, "zebra") < (2, "apple") // true because 1 is less than 2; "zebra" and "apple" are not compared (3, "apple") < (3, "bird") // true because 3 is equal to 3, and "apple" is less than "bird" (4, "dog") == (4, "dog") // true because 4 is equal to 4, and "dog" is equal to "dog"
В приведенном выше примере вы можете увидеть поведение сравнения слева направо в первой строке. Потому 1 что меньше чем 2 , считается меньше чем , независимо от любых других значений в кортежах. Неважно, что это не меньше , потому что сравнение уже определяется первыми элементами кортежей. Однако, когда первые элементы кортежей являются одинаковыми, их вторые элементы имеют по сравнению, это то , что происходит на второй и третьей линии. (1, "zebra") (2, "apple") "zebra" "apple"
Кортежи можно сравнивать с данным оператором, только если оператор можно применить к каждому значению в соответствующих кортежах. Например, как показано в приведенном ниже коде, вы можете сравнить два кортежа типа, так как и значения, и значения можно сравнить с помощью оператора. Напротив, два кортежа типа не могут сравниваться с оператором, потому что оператор не может быть применен к значениям. (String, Int) String Int < (String, Bool) < < Bool
("blue", -1) < ("purple", 1) // OK, evaluates to true ("blue", false) < ("purple", true) // Error because < can't compare Boolean values
ЗАМЕТКА
Стандартная библиотека Swift включает в себя операторы сравнения кортежей для кортежей, содержащих менее семи элементов. Чтобы сравнить кортежи с семью или более элементами, вы должны самостоятельно реализовать операторы сравнения.
Тернарный условный оператор
Тройной условный оператор является специальным оператором с тремя частями, который принимает форму . Это ярлык для оценки одного из двух выражений в зависимости от того, является ли оно истинным или ложным. Если это правда, он оценивает и возвращает свое значение; в противном случае он оценивает и возвращает свое значение. question ? answer1 : answer2 question question answer1 answer2
Тернарный условный оператор является сокращением для кода ниже:
if question < answer1 >else
Вот пример, который вычисляет высоту строки таблицы. Высота строки должна быть на 50 пунктов выше, чем высота содержимого, если строка имеет заголовок, и на 20 пунктов выше, если строка не имеет заголовка:
let contentHeight = 40 let hasHeader = true let rowHeight = contentHeight + (hasHeader ? 50 : 20) // rowHeight is equal to 90
Пример выше является сокращением для кода ниже:
let contentHeight = 40 let hasHeader = true let rowHeight: Int if hasHeader < rowHeight = contentHeight + 50 >else < rowHeight = contentHeight + 20 >// rowHeight is equal to 90
В первом примере использование троичного условного оператора означает, что ему rowHeight может быть задано правильное значение в одной строке кода, что является более кратким, чем код, использованный во втором примере.
Тернарный условный оператор обеспечивает эффективную стенограмму для решения, какое из двух выражений следует рассмотреть. Однако используйте троичный условный оператор с осторожностью. Его краткость может привести к сложному для чтения коду при чрезмерном использовании. Избегайте объединения нескольких экземпляров тернарного условного оператора в один составной оператор.
Ноль-коалесцирующий оператор
Оператор nil- coalescing ( ) разворачивает необязательное значение, если оно содержит значение, или возвращает значение по умолчанию, если оно есть . Выражение всегда имеет необязательный тип. Выражение должно соответствовать типу, который хранится внутри . a ?? b a b a nil a b a
Оператор nil-coalescing является сокращением для кода ниже:
a != nil ? a! : b
Приведенный выше код использует троичный условный оператор и принудительный unwrapping ( a! ) для доступа к значению, заключенному внутри, a когда a его нет nil , и для возврата в b противном случае. Оператор nil-coalescing предоставляет более элегантный способ инкапсулировать эту условную проверку и развертывание в сжатой и читаемой форме.
ЗАМЕТКА
Если значение не a является nil , значение b не оценивается. Это известно как оценка короткого замыкания .
В приведенном ниже примере оператор nil-coalescing выбирает имя цвета по умолчанию и необязательное имя цвета, определяемое пользователем:
let defaultColorName = "red" var userDefinedColorName: String? // defaults to nil var colorNameToUse = userDefinedColorName ?? defaultColorName // userDefinedColorName is nil, so colorNameToUse is set to the default of "red"
userDefinedColorName Переменная определяется как необязательный String , со значением по умолчанию nil . Поскольку userDefinedColorName это необязательный тип, вы можете использовать оператор nil-coalescing, чтобы рассмотреть его значение. В приведенном выше примере оператор используется для определения начального значения для String вызываемой переменной colorNameToUse . Потому userDefinedColorName что nil , выражение возвращает значение или . userDefinedColorName ?? defaultColorName defaultColorName "red"
Если вы назначите ненулевое nil значение и снова userDefinedColorName выполните проверку оператора nil-coalescing, userDefinedColorName вместо значения по умолчанию используется значение, заключенное внутри :
userDefinedColorName = "green" colorNameToUse = userDefinedColorName ?? defaultColorName // userDefinedColorName is not nil, so colorNameToUse is set to "green"
Операторы диапазона
Swift включает в себя несколько операторов диапазона , которые являются ярлыками для выражения диапазона значений.
Закрытый оператор
Диапазон оператор замкнутого ( a. b ) определяет диапазон , который проходит от a до b , и включает в себя значения a и b . Значение a не должно быть больше чем b .
Оператор закрытого диапазона полезен при итерации по диапазону, в котором вы хотите использовать все значения, например, с циклом for - in :
for index in 1. 5 < print("\(index) times 5 is \(index * 5)") >// 1 times 5 is 5 // 2 times 5 is 10 // 3 times 5 is 15 // 4 times 5 is 20 // 5 times 5 is 25
Более подробную информацию о for - in петлями см Flow Control .
Оператор полуоткрытого диапазона
Оператор полуоткрытого диапазона ( a..наполовину открыт, потому что содержит его первое значение, но не его окончательное значение. Как и в случае с оператором закрытого диапазона, значение a не должно быть больше, чем b . Если значение a равно b , то результирующий диапазон будет пустым.
Полуоткрытые диапазоны особенно полезны, когда вы работаете со списками, начинающимися с нуля, такими как массивы, где полезно подсчитывать (но не включая) длину списка:
let names = ["Anna", "Alex", "Brian", "Jack"] let count = names.count for i in 0.. // Person 1 is called Anna // Person 2 is called Alex // Person 3 is called Brian // Person 4 is called Jack
Односторонние ряды
Оператор закрытого диапазона имеет альтернативную форму для диапазонов, которые продолжаются, насколько это возможно, в одном направлении, например, диапазон, который включает все элементы массива от индекса 2 до конца массива. В этих случаях вы можете опустить значение с одной стороны оператора диапазона. Этот вид диапазона называется односторонним диапазоном, потому что оператор имеет значение только с одной стороны. Например:
for name in names[2. ] < print(name) >// Brian // Jack for name in names[. 2] < print(name) >// Anna // Alex // Brian
Оператор полуоткрытого диапазона также имеет одностороннюю форму, написанную только с его конечным значением. Так же, как когда вы включаете значение с обеих сторон, окончательное значение не входит в диапазон. Например:
for name in names[.. // Anna // Alex
Односторонние диапазоны могут использоваться в других контекстах, а не только в подписках. Вы не можете выполнять итерацию по одностороннему диапазону, в котором пропущено первое значение, потому что неясно, где должна начинаться итерация. Вы можете перебирать односторонний диапазон, в котором не указывается его окончательное значение; однако, поскольку диапазон продолжается бесконечно, убедитесь, что вы добавили явное конечное условие для цикла. Вы также можете проверить, содержит ли односторонний диапазон конкретное значение, как показано в приведенном ниже коде.
let range = . 5 range.contains(7) // false range.contains(4) // true range.contains(-1) // true
Логические Операторы
Логические операторы изменяют или объединяют значения логической логики true и false . Swift поддерживает три стандартных логических оператора в языках на основе C:
- Логическое НЕ ( !a )
- Логическое И ( ) a && b
- Логическое ИЛИ ( ) a || b
Логическое НЕ Оператор
Логический оператор НЕ ( !a ) инвертирует логическое значение , таким образом , что true становится false , и false становится true .
Логический оператор NOT является префиксным оператором и появляется непосредственно перед значением, с которым он работает, без пробелов. Его можно прочитать как «нет a », как показано в следующем примере:
let allowedEntry = false if !allowedEntry < print("ACCESS DENIED") >// Prints "ACCESS DENIED"
Фраза может быть прочитана как «если недопустимая запись». Следующая строка выполняется только в том случае, если «недопустимая запись» имеет значение true; если есть . if !allowedEntry allowedEntry false
Как и в этом примере, тщательный выбор логических констант и имен переменных может помочь сделать код читаемым и кратким, избегая двойных отрицаний или запутанных логических выражений.
Логический И Оператор
Логический оператор ( ) создает логические выражения , где оба значения должны быть для всего выражения также быть . a && b true true
Если любое значение равно false , общее выражение также будет false . Фактически, если первое значение равно false , второе значение даже не будет оцениваться, потому что оно не может сделать общее выражение равным true . Это известно как оценка короткого замыкания .
В этом примере рассматриваются два Bool значения и разрешается доступ только в том случае, если оба значения true :
let enteredDoorCode = true let passedRetinaScan = false if enteredDoorCode && passedRetinaScan < print("Welcome!") >else < print("ACCESS DENIED") >// Prints "ACCESS DENIED"
Оператор логического ИЛИ
Оператор логического ИЛИ ( ) - это инфиксный оператор, состоящий из двух соседних символов канала. Вы используете его для создания логических выражений, в которых должно быть только одно из двух значений для общего выражения . a || b true true
Как и оператор логического И выше, оператор логического ИЛИ использует оценку короткого замыкания для рассмотрения его выражений. Если левая сторона выражения логического ИЛИ равна true , правая сторона не оценивается, потому что она не может изменить результат всего выражения.
В приведенном ниже примере первое Bool значение ( hasDoorKey ) есть false , а второе значение ( knowsOverridePassword ) есть true . Поскольку одно значение - true общее выражение также оценивается true , и доступ разрешен:
let hasDoorKey = false let knowsOverridePassword = true if hasDoorKey || knowsOverridePassword < print("Welcome!") >else < print("ACCESS DENIED") >// Prints "Welcome!"
Объединение логических операторов
Вы можете объединить несколько логических операторов для создания более длинных составных выражений:
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword < print("Welcome!") >else < print("ACCESS DENIED") >// Prints "Welcome!"
В этом примере используются несколько операторов && и || операторы для создания более длинного составного выражения. Тем не менее, && и || операторы по- прежнему работают только два значения, так что это на самом деле три меньших выражения прикован вместе. Пример можно прочитать как:
Если мы ввели правильный код двери и прошли сканирование сетчатки, или у нас есть действующий ключ от двери, или если мы знаем пароль аварийного отмены, тогда разрешите доступ.
На основании значений enteredDoorCode , passedRetinaScan и hasDoorKey первые два подвыражения false . Однако пароль аварийного переопределения известен, поэтому общее составное выражение все равно оценивается как true .
ЗАМЕТКА
Логические операторы Swift && и || являются левоассоциативными, это означает, что составные выражения с несколькими логическими операторами сначала оценивают крайнее левое подвыражение.
Явные круглые скобки
Иногда полезно включать скобки, когда они не являются строго необходимыми, чтобы облегчить чтение намерения сложного выражения. В приведенном выше примере доступа к двери полезно добавить круглые скобки вокруг первой части составного выражения, чтобы сделать его намерение явным:
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword < print("Welcome!") >else < print("ACCESS DENIED") >// Prints "Welcome!"
Скобки проясняют, что первые два значения рассматриваются как часть отдельного возможного состояния в общей логике. Вывод составного выражения не меняется, но общее намерение становится понятнее читателю. Читаемость всегда предпочтительнее краткости; используйте скобки, где они помогают прояснить ваши намерения.
Операторы в Swift
Операторы — это специальные символы, которые выполняют операции над переменными и значениями. Например:
print ( 5 + 6 ) // 11
Здесь + — это оператор, который выполняет операцию сложения двух чисел: 5 и 6 .
Типы операторов в Swift:
- Арифметические операторы
- Операторы присваивания
- Операторы сравнения
- Логические операторы
- Побитовые операторы
- Другие операторы
Арифметические операторы в Swift
Арифметические операторы используются для выполнения математических операций, такие как сложение, вычитание, умножение и др. Например:
var sub = 10 - 5 // 5
Здесь оператор - является арифметическим оператором, который выполняет операцию вычитания с двумя числами. Результат присваивается переменной sub .
| Оператор | Операция | Пример |
| + | Сложение | 5 + 2 = 7 |
| − | Вычитание | 4 − 2 = 2 |
| * | Умножение | 2 * 3 = 6 |
| / | Деление | 4 / 2 = 2 |
| % | Остаток от деления | 5 % 2 = 1 |
Рассмотрим пример использования арифметических операторов в Swift:
print ( a + b )
print ( a - b )
print ( a * b )
Оператор деления / в Swift
Оператор / выполняет операцию деления между двумя числами. Тем не менее, если оба числа являются целочисленными, то в результате мы получим целое число. Например:
// Возвращает целое число
Если мы используем оператор / c числами типа с плавающей точкой, мы получим дробное число. Например:
// Возвращает дробное число
7.0 / 3.0 = 3.5
Оператор остатка от деления % в Swift
Оператор остатка от деления % возвращает остаток от деления 1-го операнда на 2-й. Например:
print ( 9 % 4 ) // 1
Примечание: Оператор % может использоваться только с целыми числами.
Операторы присваивания в Swift
Операторы присваивания используются для присваивания значений переменным. Например:
// Присваиваем значение 5 переменной x
Список операторов присваивания в Swift:
| Оператор | Операция | Пример |
| = | Присваивание | a = 4 |
| += | Сложение с присваиванием | a += 2 → a = a + 2 |
| −= | Вычитание с присваиванием | a −= 4 → a = a − 4 |
| *= | Умножение с присваиванием | a *= 5 → a = a * 5 |
| /= | Деление с присваиванием | a /= 6 → a = a / 6 |
| %= | Остаток от деления с присваиванием | a %= 7 → a = a % 7 |
Рассмотрим пример использования операторов присваивания в Swift:
// Присваиваем значение 10 переменной a
// Присваиваем результат выполнения операции сложения a + 1 переменной a
// Присваиваем результат выполнения операции вычитания a - 3 переменной a
// Присваиваем результат выполнения операции умножения a * 4 переменной a
// Присваиваем результат выполнения операции деления a / 3 переменной a
// Присваиваем результат выполнения операции остатка от деления a % 10 переменной a
Операторы сравнения в Swift
Операторы сравнения сравнивают два значения/переменные и возвращают логический результат: true или false . Например:
var a = 5 , b = 2
print ( a > b ) // true
Здесь > — это оператор сравнения, который сравнивает, является ли a больше b или нет.
| Оператор | Операция | Пример |
| == | Равно | 2 == 4 → false |
| != | Не Равно | 2 != 5 → true |
| > | Больше чем | 2 > 4 → false |
| Меньше чем | 2 4 → true | |
| >= | Больше или Равно | 2 >= 4 → false |
| Меньше или Равно | 2 4 → true |
Рассмотрим пример использования операторов сравнения в Swift:
var a = 5 , b = 2
// Оператор Равно
print ( a == b )
// Оператор Не равно
print ( a != b )
// Оператор Больше чем
print ( a > b )
// Оператор Меньше чем
print ( a < b )
// Оператор Больше или Равно
print ( a >= b )
// Оператор Меньше или Равно
print ( a <= b )
false
true
true
false
true
false
Примечание: Операторы сравнения часто используются в условиях и циклах.
Логические операторы в Swift
Логические операторы используются для проверки того, является ли выражение true или false . Они используются в логических операциях. Например:
var a = 5 , b = 6
print ( ( a > 2 ) && ( b >= 6 ) ) // true
Здесь && — это логический оператор И. Поскольку оба выражения a > 2 и b >= 6 имеют значение true , то и результат равен true .
| Оператор | Пример | Операция |
| && | a && b | Логическое И: true, если оба операнда равны true. |
| || | a || b | Логическое ИЛИ: true, если хотя бы один из операндов равен true. |
| ! | !a | Логическое НЕ: true, если операнд равен false. |
Рассмотрим пример использования логических операторов в Swift:
Продвинутые операторы

В дополнение к операторам, которые мы рассматривали в главе Базовые операторы, Swift предоставляет нам еще несколько продвинутых операторов, которые позволяют нам проводить более сложные манипуляции со значениями. Они включают в себя побитовые и операторы разрядного смещения, с которыми вы возможно знакомы из языков C или Objective-C.
В отличии от арифметических операторов C, арифметические операторы в Swift не переполняются по умолчанию. Переполнения отслеживаются и выводятся как ошибка. Для того, чтобы этого избежать, вы можете использовать оператор из второго набора арифметических операторов Swift ( &+ ). Все операторы переполнения начинаются с амперсанда ( & ).
Когда вы определяете ваши собственные структуры, классы или перечисления, то может быть полезным обеспечивать ваши собственные реализации стандартных операторов Swift, для этих пользовательских типов. Swift позволяет создавать адаптивные реализации этих операторов, так что вы можете определить их поведения для каждого конкретного типа, который вы создаете.
Вы не ограничены в предопределенных операторах. Swift дает вам свободу определять ваши собственные префиксные, инфиксные, постфиксные операторы и операторы присваивания, которым вы можете задавать собственный приоритет и ассоциативность значений. Эти операторы могут быть использованы и приняты вашим кодом, как и любой другой предопреленный оператор, вы так же можете расширить уже существующие типы, для того, чтобы они могли поддерживать ваши пользовательские операторы.
Побитовые операторы
Побитовые операторы позволяют вам манипулировать отдельными битами необработанных данных внутри структуры данных. Они часто используются в низкоуровневом программировании, например программирование графики или создание драйвера для устройства. Побитовые операторы также могут быть полезны, когда вы работаете с необработанными данными из внешних ресурсов, например, кодирование или декодирование данных для связи через собственный протокол.
Swift поддерживает все побитовые операторы, которые были основаны в C о которых мы поговорим далее.
Побитовый оператор NOT
Побитовый оператор NOT ( ~ ) инвертирует все битовые числа:

Побитовый оператор NOT является префиксным оператором и ставится прямо перед значением (без пробела), над которым он оперирует.
let initialBits: UInt8 = 0b00001111 let invertedBits = ~initialBits // равен 11110000
Целые числа типа UInt8 имеют восемь бит и могут хранить значения от 0 до 255 . В этом примере инициализируем число типа UInt8 , которое имеет бинарное значение 00001111 , которое имеет первые четыре бита равные 0 , а вторая четверка битов равна 1. Это эквивалент числа 15 .
Далее используем побитовый оператор NOT для создания новой константы invertedBits , которая равна initialBits , но только с перевернутыми битами. То есть теперь все единицы стали нулями, а нули единицами. Значение числа invertedBits равно 11110000 , что является эквивалентом 240 .
Побитовый оператор AND
Побитовый оператор AND ( & ) комбинирует два бита двух чисел. Он возвращает новое число, чье значение битов равно 1 , если только оба бита из входящих чисел были равны 1 :

В примере ниже, значения firstSixBits и lastSixBits имеют четыре бита по середине равными 1. Побитовый оператор AND комбинирует их для создания числа 00111100 , которое равно беззнаковому целому числу 60 :
let firstSixBits: UInt8 = 0b11111100 let lastSixBits: UInt8 = 0b00111111 let middleFourBits = firstSixBits & lastSixBits // равен 00111100
Побитовый оператор OR
Побитовый оператор OR ( | ) сравнивает биты двух чисел. Оператор возвращает новое число, чьи биты устанавливаются на 1 , если один из пары битов этих двух чисел имеет бит равный 1 :

В примере ниже значения someBits и moreBits имеют разные биты со значениями 1. Побитовый оператор OR комбинирует их для создания числа 11111110 , что равно беззнаковому целому числу 254 :
let someBits: UInt8 = 0b10110010 let moreBits: UInt8 = 0b01011110 let combinedbits = someBits | moreBits // равен 11111110
Побитовый оператор XOR
Побитовый оператор XOR или “оператор исключающего OR” ( ^ ), который сравнивает биты двух чисел. Оператор возвращает число, которое имеет биты равные 1 , когда биты входных чисел разные, и возвращает 0 , когда биты одинаковые:

В примере ниже, значения firstBits и otherBits каждый имеет один бит в том месте, где у другого 0. Побитовый оператор XOR устанавливает оба этих бита в качестве выходного значения. Все остальные биты повторяются, поэтому оператор возвращает 0 :
let firstBits: UInt8 = 0b00010100 let otherBits: UInt8 = 0b00000101 let outputBits = firstBits ^ otherBits // равен 00010001
Операторы побитового левого и правого сдвига
Оператор побитового левого сдвига ( > ) двигают все биты числа влево или вправо на определенное количество мест, в зависимости от правил, которые определены ниже.
Побитовые операторы левого и правого сдвига имеют эффект умножения или деления числа на 2. Сдвигая биты целого числа влево на одну позицию, мы получаем удвоенное первоначальное число, в то время как, двигая его вправо на одну позицию, мы получаем первоначальное число поделённое на 2 .
Поведение сдвига для беззнаковых целых чисел
Поведение побитового сдвига имеет следующие правила:
- Существующие биты сдвигаются вправо или влево на требуемое число позиций.
- Любые биты, которые вышли за границы числа, отбрасываются.
- На пустующие позиции сдвинутых битов вставляются нули.
Такой подход называется логическим сдвигом.
Иллюстрация внизу отображает результат смещения 11111111 > 1 (что означает 11111111 сдвинутые на 1 вправо). Голубые цифры - сдвинутые, серые - отброшенные, оранжевые - вставленные:

Вот как выглядит побитовый сдвиг в виде Swift кода:
let shiftBits: UInt8 = 4 // 00000100 бинарный вид shiftBits > 2 // 00000001
Вы можете использовать побитовый сдвиг для кодирования и декодирования значений внутри других типов данных:
let pink: UInt32 = 0xCC6699 let redComponent = (pink & 0xFF0000) >> 16 // redComponent равен 0xCC, или 204 let greenComponent = (pink & 0x00FF00) >> 8 // greenComponent равен 0x66, или 102 let blueComponent = pink & 0x0000FF // blueComponent равен 0x99, или 153
Этот пример использует UInt32 , который называется pink , для хранения значения розового цвета из файла CSS. Значение розового цвета # CC6699 , что записывается в виде шестнадцатеричном представлении Swift как 0xCC6699 . Этот цвет затем раскладывается на его красный( CC ), зеленый ( 66 ) и голубой ( 99 ) компоненты при помощи побитового оператора AND ( & ) и побитового оператора правого сдвига ( >> ).
Красный компонент получен с помощью побитового оператора AND между числами 0xCC6699 и 0xFF0000 . Нули в 0xFF0000 фактически являются “маской” для третьего и четвертого бита в 0xCC6699 , тем самым заставляя игнорировать 6699 , и оставляя 0xCC0000 в качестве результата.
После этого число сдвигается на 16 позиций вправо ( >> 16 ). Каждая пара символов в шестнадцатеричном числе использует 8 битов, так что сдвиг вправо на 16 позиций преобразует число 0xCC0000 в 0x0000CC . Это то же самое, что и 0xCC , которое имеет целое значение равное 204 .
Аналогично с зеленым компонентом, который получается путем использования побитового оператора AND между числами 0xCC6699 и 0x00FF00 , который в свою очередь дает нам выходное значение 0x006600 . Это выходное значение затем сдвигается на восемь позиций вправо, давая нам значение 0x66 , что имеет целое значение равное 102 .
Ну а теперь последний синий компонент, который получается при использовании побитового оператора AND между числами 0xCC6699 и 0x0000FF , что в свою очередь дает нам выходное значение равное 0x000099 . Таким образом, нам не нужно сдвигать это вправо, так как 0x000099 уже равно 0x99 , что имеет целое значение равное 153 .
Поведение побитового сдвига для знаковых целых чисел
Поведение побитового сдвига для знаковых целых чисел более сложное, чем для беззнаковых, из-за того, как они представлены в бинарном виде. (Пример ниже основан на восьми битовом знаковом целом числе для простоты примера, однако этот принцип применим к знаковым целым числам любого размера).
Знаковые целые числа используют первый бит (известный как знаковый бит) для индикации того, является ли число положительным или отрицательным. Значение знакового бита равное 0 свидетельствует о положительном числе, 1 - отрицательном.
Остальные биты (известные как биты значения) хранят фактическое значение. Положительные числа хранятся в точности так же как и беззнаковые целые числа, считая от 0. Вот как выглядят биты внутри Int8 для числа 4 :

Знаковый бит равен 0 (число положительное), остальные семь битов означают число 4 , записанное в бинарной форме.
Однако отрицательные числа хранятся иначе. Они хранятся путем вычитания их абсолютного значения из 2 в степени n, где n - количество битов значения.
Вот как выглядит биты внутри Int8 для числа - 4 :

В этот раз, знаковый бит равен 1 (число отрицательное), а остальные семь знаковых бита имеют бинарное значение числа 124 (что означает 128 - 4):

Кодирование отрицательных чисел известно под названием дополнительный код. Это может показаться необычным способом для отображения отрицательных чисел, но в нем есть несколько преимуществ.
Первое. Вы можете добавить - 1 к - 4 , просто выполняя стандартное сложение всех восьми битов (включая и восьмой бит), и отбрасывая все, что не поместится в ваши восемь бит:

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

Эти действия гарантируют вам, что знаковые числа имеют тот же знак, после того как они сдвинуты вправо, и эти действия известны как арифметический сдвиг.
Из-за такого способа хранения положительных и отрицательных чисел, сдвиг вправо двигает их значение ближе к нулю. Оставляя знаковый бит тем же самым в течение побитового сдвига, означает, что ваше отрицательное число, так же и остается отрицательным, в то время как его значение так же движется к нулю.
Операторы переполнения
Если вы попытаетесь ввести число в целочисленную константу или переменную, которая не может держать это число, то по умолчанию Swift выдаст сообщение об ошибке, а не будет создавать недействительное значение. Это поведение дает дополнительную безопасность, когда вы работаете с числами, которые слишком велики или слишком малы.
Для примера, целочисленный тип Int16 может держать любое знаковое целое число от - 32768 и до 32767 . Если вы попытаетесь установить число (константу или переменную) типа Int16 за границами приведенного диапазона, то вы получите ошибку:
var potentialOverflow = Int16.max // potentialOverflow равняется 32767, что является самым большим значением, которое может содержаться в Int16 potentialOverflow += 1 // это вызовет ошибку
Обеспечивая обработку ошибки, когда значение является слишком большим или слишком маленьким, вы получаете намного большую гибкость, для кодирования краевых условий.
Однако, когда вы специально хотите осуществить условие переполнения, чтобы обрезать количество доступных битов, то вы можете получить именно такое поведение, вместо отчета об ошибке переполнения. Swift предоставляет три арифметических оператора переполнения, которые помогают перейти к поведению переполнения для целочисленных вычислений. Все эти операторы начинаются с символа амперсанда ( & ):
- Оператор переполнения с добавлением ( &+ )
- Оператор переполнения с вычитанием ( &- )
- Оператор переполнения с умножением ( & *)
Переполнение значения
Числа могут переполняться как в положительную, так и в отрицательную сторону.
Ниже приведен пример того, что случится, когда беззнаковое значение позволяет переполнить себя, с использованием оператора ( &+ ):
var willOverflow = UInt8.max // willOverflow равняется 255, что является наибольшим числом, которое может держать UInt willOverflow = willOverflow &+ 1 // willOverflow теперь равно 0
Переменная willOverflow инициализирована самым большим числом, которое может держать UInt8 ( 255 или в бинарном виде 11111111 ). Затем оно увеличивается на 1 при помощи оператора переполнения ( &+ ). Это выталкивает бинарное представление размерности UInt8 , вызывая тем самым переполнение границ, что отображено на диаграмме ниже. Значение, которое остается в пределах границ значения типа UInt8 после переполнения и добавления выглядит как 00000000 , или попросту 0 в десятичной форме:

Числа так же могут быть слишком маленькими, чтобы соответствовать определенному типу. Ниже приведен пример с использованием оператора недополнения ( &- )
var unsignedOverflow = UInt8.min // unsignedOverflow равен 0, что является наименьшим возможным значением UInt8 unsignedOverflow = unsignedOverflow &- 1 // unsignedOverflow теперь равно 255
Самое маленькое значение, которое может держать UInt8 равно 0 (что отображается как 00000000 в восьмибитной бинарной форме). Если вы из 00000000 вычтите 1 , с использованием оператора недополнения, число переполнится в обратную сторону к 11111111 , или к 255 в десятичной форме:

Аналогичное недополнение случается и с знаковыми целыми числами. Все вычитание для знаковых целых чисел проводится как прямое бинарное вычитание с учетом знакового бита, в качестве части вычитаемых чисел, что описано в Операторы побитового левого и правого сдвига.
var signedUnderflow = Int8.min // signedUnderflow равняется -128, что является самым маленьким числом, которое может держать Int8 signedUnderflow = signedUnderflow &- 1 // signedUnderflow теперь равняется 127
Самым маленьким числом, которое может держать Int8 , является –128 , что записывается в бинарной форме как 10000000 . Вычитая 1 из этого бинарного числа с оператором недополнения, дает нам значение 01111111 , что переключает наш знаковый бит на противоположный и дает нам положительное 127 , что является самым большим числом, которое может держать Int8 :

Конечный результат поведения переполнения и недополнения описан выше и одинаково работает как для знаковых, так и для беззнаковых целых чисел. Переполнение всегда переворачивает значение с самого большого на самое маленькое, недополнение всегда переворачивает самое маленькое число на самое большое.
Приоритет и ассоциативность
Оператор приоритета дает некоторым операторам более высокий приоритет по сравнению с остальными. В выражении сначала применяются эти операторы, затем все остальные.
Оператор ассоциативности определяет то, как операторы одного приоритета сгруппированы вместе (или ассоциированы друг с другом), то есть либо они сгруппированы слева, либо справа. Думайте об этом как “они связаны с выражением слева” или “они связаны с выражением справа”.
Это важно учитывать приоритет и ассоциативность каждого оператора, когда работаете с порядком, в котором должно считаться выражение. Вот простой пример. Почему данное выражение имеет равенство 17 ?
2 + 3 % 4 * 5 // это равно 17
Если вы прочитаете это выражение строго слева направо, то вы можете ожидать действия в таком порядке:
-
-
- 2 плюс 3 равняется 5
- 5 остаток от деления на 4 равен 1
- 1 умножаем на 5 и получаем 5
Однако, как не крути, правильный ответ равен 17 , а не 5 . Операторы более высокого приоритета выполняются раньше операторов более низкого приоритета. В Swift, как и в C, оператор умножения ( * ) и оператор остатка ( % ) имеют более высокий приоритет, чем оператор сложения ( + ). В результате они оба вычисляются раньше, чем вычисляется оператор сложения.
Однако оператор умножения и оператор остатка имеют один и тот же приоритет по отношению друг к другу. Для выяснения точного порядка вычисления вы должны обратиться к их ассоциативности. Операторы умножения и остатка оба ассоциируются с выражением слева от себя. Представляйте это, как будто вы добавили скобки вокруг этих частей выражения, начиная слева:
2 + ((3 % 4) * 5)( 3 % 4 ) равно 3 , значит можно записать:
2 + (3 * 5)( 3 * 5 ) равно 15 , и значит мы можем записать:
2 + 15Таким образом наш конечный результат равен 17 .
Для получения информации об операторах, предоставляемых стандартной библиотекой Swift, включая полный список групп приоритета операторов и параметров ассоциативности, см. Объявление операторов.
Заметка
Правила приоритета и ассоциативности операторов Swift проще и более предсказуемые чем в C или Objective-C. Однако это означает, что они ведут себя не так же как они вели себя в этих C-языках. Будьте внимательны с тем, как ведут себя операторы взаимодействия при переносе кода в Swift.
Операторные функции
Классы и структуры могут предоставлять свои собственные реализации существующих операторов. Действие переопределения оператора известно как перегрузка существующего оператора.
Пример ниже отображает как можно реализовать арифметический оператор сложения ( + ) для пользовательской структуры. Арифметический оператор сложения является бинарным оператором, потому что он оперирует с двумя операндами, то есть он является инфиксным, потому как вставляется между двумя операндами.
Пример определяет структуру Vector2D для двухмерного вектора положения (x, y) , за которой идет статическая функция, которая добавляет друг к другу экземпляры структуры Vector2D :
struct Vector2D < var x = 0.0, y = 0.0 >extension Vector2D < static func + (left: Vector2D, right: Vector2D) ->Vector2D < return Vector2D(x: left.x + right.x, y: left.y + right.y) >>Операторный метод определен как метод типа Vector2D с именем метода, которое совпадает с именем оператора, который перегружают ( + ). Так как сложение не является неотъемлемой частью поведения вектора, метод типа определен в расширении нашего Vector2D , а не в основной структуре Vector2D . Так как арифметический оператор сложения является бинарным оператором, то этот оператор принимает два параметра типа Vector2D и возвращает единственное выходное значение, которое тоже имеет тип Vector2D .
В этой реализации входные параметры имеют имена left и right , для отображения экземпляров Vector2D , которые будут по левую и по правую сторону от оператора + . Функция возвращает новый экземпляр Vector2D , x и y которого инициализированы суммой свойств x и y из двух экземпляров Vector2D , которые были добавлены друг другу.
Метод типа может использоваться как инфиксный оператор между существующими экземплярами Vector2D :
let vector = Vector2D(x: 3.0, y: 1.0) let anotherVector = Vector2D(x: 2.0, y: 4.0) let combinedVector = vector + anotherVector // combinedVector является экземпляром Vector2D, который имеет значения (5.0, 5.0)Этот пример складывает два вектора вместе (3.0, 1.0) и (2.0, 4.0) для создания вектора (5.0, 5.0) , который нарисован ниже:

Префиксные и постфиксные операторы
Пример, отображенный выше, демонстрирует пользовательскую реализацию бинарного инфиксного оператора. Классы и структуры так же могут обеспечивать реализацию стандартных унарных операторов. Унарные операторы работают с одним операндом. Они бывают префиксными, если они предшествуют их операнду (например, -a ) или постфиксными, если они следуют за операндом (например b! ).
Вы реализуете префиксный или постфиксный унарный оператор при помощи модификаторов prefix или postfix перед ключевым словом func , когда объявляете операторную функцию:
extension Vector2D < static prefix func - (vector: Vector2D) ->Vector2D < return Vector2D(x: -vector.x, y: -vector.y) >>Пример выше реализует унарный оператор ( -a ) для экземпляров Vector2D . Оператор унарного минуса является префиксным оператором, таким образом эта функция должна быть модифицирована при помощи prefix модификатора.
Для простых числовых значений оператор унарного минуса конвертирует положительные числа в их негативный эквивалент и наоборот. Соответствующая реализация для экземпляров Vector2D проводит операции и на x , и на y свойствах:
let positive = Vector2D(x: 3.0, y: 4.0) let negative = -positive // negative - экземпляр Vector2D со значениями (-3.0, -4.0) let alsoPositive = -negative // alsoPositive - экземпляр Vector2D со значениями (3.0, 4.0)Составные операторы присваивания
Составные операторы присваивания комбинируют оператор присваивания ( = ) с другим оператором. Например, оператор сложения-присваивания ( += ) комбинирует в себе оператор добавления и оператор присваивания. Вы обозначаете левый входной параметр составного оператора как inout , потому что именно эта величина и будет изменена напрямую изнутри самой операторной функции.
Пример ниже реализует операторную функцию добавления-присваивания для экземпляров Vector2D :
extension Vector2D < static func += (left: inout Vector2D, right: Vector2D) < left = left + right >>Так как оператор сложения был определен ранее, то вам не нужно реализовывать процесс сложения здесь. Вместо этого оператор сложения-присваивания использует существующую операторную функцию сложения и использует ее для установки нового значения левому значению, как сумму левого и правого значений:
var original = Vector2D(x: 1.0, y: 2.0) let vectorToAdd = Vector2D(x: 3.0, y: 4.0) original += vectorToAdd // original теперь имеет значения (4.0, 6.0)Заметка
Нет такой возможности перегрузить оператор присваивания ( = ). Только составные операторы могут быть перегружены. Тернарный оператор ( a ? b : c ) так же не может быть перегружен.
Операторы эквивалентности
Пользовательские классы и структуры не получают дефолтной реализации эквивалентных операторов, известных как “равен чему-то” оператор ( == ) или “не равен чему-то” ( != ).
Чтобы использовать операторы эквивалентности для проверки эквивалентности вашего собственного пользовательского типа, предоставьте реализацию для этих операторов тем же самым способом, что и для инфиксных операторов и добавьте соответствие протоколу стандартной библиотеки Equatable :
extension Vector2D: Equatable < static func == (left: Vector2D, right: Vector2D) ->Bool < return (left.x == right.x) && (left.y == right.y) >>Пример выше реализует оператор “равен чему-то” ( == ) для проверки эквивалентности значений двух экземпляров Vector2D . В контексте Vector2D имеет смысл считать, что “равно чему-то” означает, что “оба экземпляра имеют одни и те же значения x и y ”, таким образом это является той логикой, которая используется при реализации оператора. Пример так же реализует оператор “не равен чему-то” ( != ), который просто возвращает обратный результат оператора “равен чему-то”.
Теперь вы можете использовать эти операторы для проверки того, эквивалентны ли экземпляры Vector2D друг другу или нет:
let twoThree = Vector2D(x: 2.0, y: 3.0) let anotherTwoThree = Vector2D(x: 2.0, y: 3.0) if twoThree == anotherTwoThree < print("Эти два вектора эквиваленты.") >// Выведет "Эти два вектора эквиваленты."Swift предоставляет синтезированные реализации операторов эквивалентности для следующих пользовательских типов:
- Структур, имеющих только свойства хранения, соответствующие протоколу Equatable
- Перечислений, имеющих только ассоциированные типы, соответствующие протоколу Equatable
- Перечислений, не имеющих связанных типов
Объявите о соответствии протоколу Equatable в исходной реализации для получения этих дефолтных реализаций.
Приведенный ниже пример определяет структуру Vector3D для трехмерного вектора положения (x, y, z) , аналогичную структуре Vector2D . Поскольку свойства x , y и z являются эквивалентными, Vector3D принимает стандартные реализации операторов эквивалентности.
struct Vector3D: Equatable < var x = 0.0, y = 0.0, z = 0.0 >let twoThreeFour = Vector3D(x: 2.0, y: 3.0, z: 4.0) let anotherTwoThreeFour = Vector3D(x: 2.0, y: 3.0, z: 4.0) if twoThreeFour == anotherTwoThreeFour < print("These two vectors are also equivalent.") >// Выведет "These two vectors are also equivalent."Пользовательские операторы
Вы можете объявить и реализовать ваши собственные пользовательские операторы в дополнение к стандартным операторам Swift. Список символов, которые можно использовать для определения пользовательских операторов, см. в разделе «Операторы».
Новые операторы объявляются на глобальном уровне при помощи ключевого слова operator и отмечаются модификатором prefix , infix , postfix :
prefix operator +++Пример выше определяет новый префиксный оператор +++ . Этот оператор не имеет никакого значения в Swift, таким образом мы даем ему собственное назначение, которое описано чуть ниже, которое имеет специфический контекст работы с экземплярами Vector2D . Для целей этого примера, оператор +++ рассматривается как новый “префиксный двойной” оператор. Он удваивает значения x и y экземпляра Vector2D , путем добавления вектора самому себе при помощи оператора сложения-присваивания, который мы определили ранее. Для реализации +++ оператора мы добавим метод типа Vector2D с именем +++ как показано ниже:
extension Vector2D < static prefix func +++ (vector: inout Vector2D) ->Vector2D < vector += vector return vector >> var toBeDoubled = Vector2D(x: 1.0, y: 4.0) let afterDoubling = +++toBeDoubled // toBeDoubled имеет значения (2.0, 8.0) // afterDoubling так же имеет значения (2.0, 8.0)Приоритет для пользовательских инфиксных операторов
Каждый пользовательский infix оператор принадлежит к своей приоритетной группе. Группа приоритета определяет приоритет оператора по отношению к другим инфиксным операторам, так же как и ассоциативность оператора. Посмотрите главу Приоритет и ассоциативность для объяснения того, как эти две характеристики влияют на взаимодействие инфиксных операторов между собой.
Пользовательскому инфиксному оператору, который явно не размещен в приоритетной группе, предоставляется дефолтная группа приоритета, которая является по приоритету следующей после тернарного условного оператора.
Следующий пример определяет новый инфиксный оператор +- левой ассоциативности и с приоритетом AdditionPrecedence :
infix operator +-: AdditionPrecedence extension Vector2D < static func +- (left: Vector2D, right: Vector2D) ->Vector2D < return Vector2D(x: left.x + right.x, y: left.y - right.y) >> let firstVector = Vector2D(x: 1.0, y: 2.0) let secondVector = Vector2D(x: 3.0, y: 4.0) let plusMinusVector = firstVector +- secondVector // plusMinusVector является экземпляром Vector2D со значениями (4.0, -2.0)Этот оператор складывает значения x двух векторов и вычитает значение y второго вектора из значения y первого вектора. Так как этот оператор в сущности является оператором “сложения”, то приоритет будет равным операторам сложения ( + ) и вычитания ( - ). Для получения информации об операторах, представленных стандартной библиотекой Swift, включая список настроек ассоциативности и групп приоритета смотрите раздел "Объявления операторов". Для более полной информации по группам приоритета и для ознакомления с синтаксисом создания своих собственных операторов и групп ассоциативности смотрите "Объявление оператора".
Заметка
Вы не указываете приоритет, когда определяете префиксный и постфиксные операторы. Однако, если вы воздействуете на операнд сразу двумя операторами (префиксным и постфиксным), то первым будет применен постфиксный оператор.
Result Builders
Result Builder - это определяемый вами тип, который добавляет синтаксис для создания вложенных данных, таких как список или дерево, естественным, декларативным образом. Код, использующий result builder, может включать обычный синтаксис Swift, например if и for , для обработки условных или повторяющихся фрагментов данных.
В приведенном ниже коде определены несколько типов рисования на одной линии с использованием звездочек и текста.
protocol Drawable < func draw() ->String > struct Line: Drawable < var elements: [Drawable] func draw() ->String < return elements.map < $0.draw() >.joined(separator: "") > > struct Text: Drawable < var content: String init(_ content: String) < self.content = content >func draw() -> String < return content >> struct Space: Drawable < func draw() ->String < return " " >> struct Stars: Drawable < var length: Int func draw() ->String < return String(repeating: "*", count: length) >> struct AllCaps: Drawable < var content: Drawable func draw() ->String < return content.draw().uppercased() >>Протокол Drawable определяет требования к чему-то, что можно нарисовать, например линии или фигуре: тип должен реализовывать метод draw() . Структура Line представляет собой однолинейный рисунок и служит контейнером верхнего уровня для большинства рисунков. Чтобы нарисовать линию, структура вызывает draw() для каждого из компонентов линии, а затем объединяет результирующие строки в одну строку. Структура Text оборачивает строку, чтобы сделать ее частью рисунка. Структура AllCaps оборачивает и изменяет другой рисунок, преобразуя любой текст в рисунке в верхний регистр.
Можно создать рисунок при помощи этих типов, вызвав их инициализаторы.
let name: String? = "Ravi Patel" let manualDrawing = Line(elements: [ Stars(length: 3), Text("Hello"), Space(), AllCaps(content: Text((name ?? "World") + "!")), Stars(length: 2), ]) print(manualDrawing.draw()) // Выведет "***Hello RAVI PATEL!**"Этот код работает, но немного неудобен. Глубоко вложенные круглые скобки после AllCaps трудночитаемы. Логика отката для использования «World» , когда name равно nil , должна быть встроена с использованием оператора ?? , что было бы сложно использовать в более сложных кейсах. Если вам нужно было встроить инструкцию switch или цикл for для создания рисунка, то это было бы просто невозможно. Result Builder позволяет вам переписать такой код, чтобы он выглядел как обычный код на Swift.
Чтобы определить Result Builder, вы пишете атрибут @resultBuilder в объявлении типа. Например, этот код определяет Result Builder под названием DrawingBuilder, который позволяет вам использовать декларативный синтаксис для описания рисунка:
@resultBuilder struct DrawingBuilder < static func buildBlock(_ components: Drawable. ) ->Drawable < return Line(elements: components) >static func buildEither(first: Drawable) -> Drawable < return first >static func buildEither(second: Drawable) -> Drawable < return second >>Структура DrawingBuilder определяет три метода, которые реализуют части синтаксиса Result Builder. Метод buildBlock(_ 🙂 добавляет поддержку записи серии строк в блоке кода. Он объединяет компоненты в этом блоке в линию. Методы buildEither(first 🙂 и buildEither(second 🙂 добавляют поддержку if-else.
Вы можете применить атрибут @DrawingBuilder к параметру функции, который превращает закрытие, переданное в функцию, в значение, которое построитель результатов создает из этого закрытия. Например:
func draw(@DrawingBuilder content: () -> Drawable) -> Drawable < return content() >func caps(@DrawingBuilder content: () -> Drawable) -> Drawable < return AllCaps(content: content()) >func makeGreeting(for name: String? = nil) -> Drawable < let greeting = draw < Stars(length: 3) Text("Hello") Space() caps < if let name = name < Text(name + "!") >else < Text("World!") >> Stars(length: 2) > return greeting > let genericGreeting = makeGreeting() print(genericGreeting.draw()) // Выведет "***Hello WORLD!**" let personalGreeting = makeGreeting(for: "Ravi Patel") print(personalGreeting.draw()) // Выведет "***Hello RAVI PATEL!**"Функция makeGreeting(for 🙂 принимает параметр имени и использует его для рисования персонализированного приветствия. Функции draw(_ 🙂 и caps(_ 🙂 принимают в качестве аргумента одно закрытие, которое помечается атрибутом @DrawingBuilder . Когда вы вызываете эти функции, вы используете специальный синтаксис, который определяет DrawingBuilder . Swift преобразует это декларативное описание рисунка в серию вызовов методов в DrawingBuilder для создания значения, переданного в качестве аргумента функции. Например, Swift преобразует вызов caps(_ 🙂 в этом примере в код, подобный следующему:
let capsDrawing = caps < let partialDrawing: Drawable if let name = name < let text = Text(name + "!") partialDrawing = DrawingBuilder.buildEither(first: text) >else < let text = Text("World!") partialDrawing = DrawingBuilder.buildEither(second: text) >return partialDrawing >Swift преобразует блок if-else в вызовы методов buildEither(first 🙂 и buildEither(second 🙂 . Хотя вы не вызываете эти методы в собственном коде, отображение результата преобразования позволяет легче увидеть, как Swift преобразует ваш код, когда вы используете синтаксис DrawingBuilder .
Чтобы добавить поддержку записи для циклов в специальном синтаксисе рисования, добавьте метод buildArray(_ :).
extension DrawingBuilder < static func buildArray(_ components: [Drawable]) ->Drawable < return Line(elements: components) >> let manyStars = draw < Text("Stars:") for length in 1. 3 < Space() Stars(length: length) >>В приведенном выше коде цикл for создает массив рисунков, а метод buildArray(_ 🙂 превращает этот массив в Line .
Свифт – Операторы
Оператор – это символ, который указывает компилятору выполнять определенные математические или логические манипуляции. Objective-C богат встроенными операторами и предоставляет следующие типы операторов –
- Арифметические Операторы
- Операторы сравнения
- Логические Операторы
- Битовые операторы
- Операторы присваивания
- Операторы диапазона
- Разные Операторы
Этот урок объяснит один за другим арифметические, реляционные, логические, побитовые, присваивания и другие операторы.
Арифметические Операторы
В следующей таблице приведены все арифметические операторы, поддерживаемые языком Swift 4. Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда –
оператор Описание пример + Добавляет два операнда А + Б даст 30 – Вычитает второй операнд из первого A – B даст -10 * Умножает оба операнда А * Б даст 200 / Делит числитель на знаменатель Б / у даст 2 % Оператор модуля и остаток от целочисленного / делительного числа B% A даст 0 Операторы сравнения
В следующей таблице показаны все реляционные операторы, поддерживаемые языком Swift 4. Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда –
оператор Описание пример == Проверяет, равны ли значения двух операндов или нет; если да, то условие становится истинным. (A == B) не соответствует действительности. знак равно Проверяет, равны ли значения двух операндов или нет; если значения не равны, то условие становится истинным. (A! = B) верно. > Проверяет, больше ли значение левого операнда, чем значение правого операнда; если да, то условие становится истинным. (A> B) не соответствует действительности. Проверяет, меньше ли значение левого операнда, чем значение правого операнда; если да, то условие становится истинным. (A > = Проверяет, больше ли значение левого операнда или равно значению правого операнда; если да, то условие становится истинным. (A> = B) не соответствует действительности. Проверяет, меньше ли значение левого операнда или равно значению правого операнда; если да, то условие становится истинным. (A Логические Операторы
В следующей таблице приведены все логические операторы, поддерживаемые языком Swift 4. Предположим, что переменная A содержит 1, а переменная B содержит 0, тогда –
оператор Описание пример && Называется логический оператор И. Если оба операнда отличны от нуля, условие становится истинным. (A && B) неверно. || Вызывается логическим оператором ИЛИ. Если любой из двух операндов отличен от нуля, условие становится истинным. (A || B) верно. ! Вызывается логическим оператором НЕ. Используйте для изменения логического состояния своего операнда. Если условие истинно, то оператор Logical NOT сделает его ложным. ! (A && B) верно. Битовые операторы
Побитовые операторы работают с битами и выполняют побитовые операции. Таблицы истинности для &, | и ^ следующие:
п Q р & д р | д р ^ д 0 0 0 0 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 1 Assume A = 60; and B = 13; In binary format, they will be as follows: A = 0011 1100 B = 0000 1101 ----------------- A & B = 0000 1100 A|B = 0011 1101 A^B = 0011 0001 ~A = 1100 0011
Побитовые операторы, поддерживаемые языком Swift 4, перечислены в следующей таблице. Предположим, что переменная A содержит 60, а переменная B содержит 13, тогда 7−
оператор Описание пример & Двоичный оператор AND немного копирует результат, если он существует в обоих операндах. (A & B) даст 12, что составляет 0000 1100 | Оператор двоичного ИЛИ копирует немного, если он существует в любом из операндов. (A | B) даст 61, что составляет 0011 1101 ^ Двоичный оператор XOR копирует бит, если он установлен в одном операнде, но не в обоих. (A ^ B) даст 49, что составляет 0011 0001 ~ Оператор дополнения двоичных единиц является унарным и имеет эффект «переворачивания» битов. (~ A) даст -61, что составляет 1100 0011 в форме дополнения 2. Двоичный оператор левого сдвига. Значение левого операнда перемещается влево на количество битов, указанное правым операндом. (A >> Оператор двоичного правого сдвига. Значение левого операнда перемещается вправо на количество битов, указанное правым операндом. A >> 2 даст 15, что составляет 0000 1111 Операторы присваивания
SSwift 4 поддерживает следующие операторы присваивания –
оператор Описание пример знак равно Простой оператор присваивания, присваивает значения от правых операндов к левому операнду C = A + B назначит значение A + B в C + = Добавить оператор присваивания И добавляет правый операнд к левому операнду и присваивает результат левому операнду C + = A эквивалентно C = C + A знак равно Вычитание И оператор присваивания, вычитает правый операнд из левого операнда и присваивает результат левому операнду C – = A эквивалентно C = C – A знак равно Оператор присваивания умножения И, умножает правый операнд на левый операнд и присваивает результат левому операнду C * = A эквивалентно C = C * A знак равно Оператор деления И присваивания, делит левый операнд на правый операнд и присваивает результат левому операнду C / = A эквивалентно C = C / A знак равно Модуль и оператор присваивания, принимает модуль с использованием двух операндов и присваивает результат левому операнду C% = A эквивалентно C = C% A Левый сдвиг И оператор присваивания C >> = Оператор правого сдвига И присваивания C >> = 2 – это то же самое, что C = C >> 2 знак равно Побитовое И оператор присваивания C & = 2 совпадает с C = C & 2 ^ = побитовое исключающее ИЛИ и оператор присваивания C ^ = 2 совпадает с C = C ^ 2 | = побитовое ИЛИ и оператор присваивания C | = 2 – это то же самое, что C = C | 2 Операторы диапазона
Swift 4 включает в себя два оператора диапазона, которые являются ярлыками для выражения диапазона значений. Следующая таблица объясняет эти два оператора.
a…, определяет диапазон, который проходит от a до конца элементов
… A, определяет диапазон, начиная от начала до
1… дает 1, 2,3… конец элементов
… 2 дает начало… 1,2
a…, определяет диапазон, который проходит от a до конца элементов
… A, определяет диапазон, начиная от начала до
1… дает 1, 2,3… конец элементов
… 2 дает начало… 1,2
Разные Операторы
Swift 4 поддерживает несколько других важных операторов, включая диапазон и? : которые объяснены в следующей таблице.
оператор Описание пример Унарный минус Знак числового значения можно переключать с помощью префикса – -3 или -4 Унарий Плюс Возвращает значение, с которым он работает, без каких-либо изменений. +6 дает 6 Троичный условный Состояние ? X: Y Если условие верно? Тогда значение X: в противном случае значение Y Приоритет операторов
Приоритет оператора определяет группировку терминов в выражении. Это влияет на то, как оценивается выражение. Некоторые операторы имеют более высокий приоритет, чем другие; например, оператор умножения имеет более высокий приоритет, чем оператор сложения.
Например, х = 7 + 3 * 2; здесь x назначено 13, а не 20, потому что оператор * имеет более высокий приоритет, чем +, поэтому он сначала умножается на 3 * 2, а затем прибавляется к 7.
Здесь операторы с самым высоким приоритетом отображаются вверху таблицы, а операторы с самым низким – внизу. Внутри выражения операторы с более высоким приоритетом будут оцениваться первыми.
-