Основные операторы
Выполняют операции, такие как присваивание, арифметические и сравнения.
Оператор — это специальный символ или фраза, используемые для проверки, изменения или объединения значений. Например, оператор сложения (+) складывает два числа, как в let i = 1 + 2, а логический оператор И (&&) объединяет два булевых значения, как в if enteredDoorCode && passedRetinaScan.
Swift поддерживает операторы, которые вы уже знаете из языков, таких как C, и улучшает несколько возможностей, чтобы устранить распространённые ошибки программирования. Оператор присваивания (=) не возвращает значение, чтобы предотвратить его случайное использование вместо оператора равенства (==). Арифметические операторы (+, -, *, /, % и т. д.) обнаруживают и запрещают переполнение значений, чтобы избежать неожиданных результатов при работе с числами, которые становятся больше или меньше допустимого диапазона значений для типа, хранящего их. Вы можете включить поведение переполнения значений, используя операторы переполнения Swift, как описано в <doc:AdvancedOperators#Overflow-Operators>.
Swift также предоставляет операторы диапазона, которых нет в C, такие как a..<b и a...b, как сокращение для выражения диапазона значений.
В этой главе описаны распространённые операторы в Swift. AdvancedOperators описывает расширенные операторы 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 isn't valid, because x = y doesn't return a value.
} Эта функция предотвращает случайное использование оператора присваивания (=) вместо оператора равенства (==). Делая if x = y недопустимым, Swift помогает избежать подобных ошибок в вашем коде.
Арифметические операторы
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). См. <doc:AdvancedOperators#Overflow-Operators>.
Оператор сложения также поддерживает конкатенацию String:
"hello, " + "world" // equals "hello, world"
Оператор остатка
Оператор остатка (a % b) определяет, сколько кратных b поместится в a и возвращает оставшееся значение (известное как остаток).
Примечание: Оператор остатка (
%) также известен как оператор модуля в других языках. Однако его поведение в Swift для отрицательных чисел означает, что строго говоря, это оператор остатка, а не операция модуля.
Вот как работает оператор остатка. Чтобы вычислить 9 % 4, сначала необходимо определить, сколько 4 поместится в 9:
Вы можете поместить две 4 в 9, а остаток равен 1 (показано оранжевым цветом).
В Swift это записывается как:
9 % 4 // equals 1
Чтобы определить ответ для a % b, оператор % вычисляет следующее уравнение и возвращает remainder в качестве результата:
a = (b x some multiplier) + remainder
где some multiplier — это наибольшее количество кратных b, которые поместятся в a.
Подставляя 9 и 4 в это уравнение, получаем:
9 = (4 x 2) + 1
Такой же метод применяется при вычислении остатка для отрицательного значения a:
-9 % 4 // equals -1
Подставляя -9 и 4 в уравнение, получаем:
-9 = (4 x -2) + -1
что даёт значение остатка -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 предоставляет составные операторы присваивания, которые объединяют присваивание (=) с другой операцией. Одним из примеров является оператор сложения присваивания (+=):
var a = 1 a += 2 // a is now equal to 3
Выражение a += 2 — это сокращённая форма a = a + 2. По сути, сложение и присваивание объединены в один оператор, который выполняет обе задачи одновременно.
Примечание: Составные операторы присваивания не возвращают значения. Например, вы не можете написать
let b = a += 2.
Дополнительную информацию об операторах, предоставляемых стандартной библиотекой Swift, см. в Operator Declarations.
Операторы сравнения
Swift поддерживает следующие операторы сравнения:
- Равно (
a == b) - Не равно (
a != b) - Больше (
a > b) - Меньше (
a < b) - Больше или равно (
a >= b) - Меньше или равно (
a <= b)
Примечание: Swift также предоставляет два оператора тождества (
===и!==), которые используются для проверки, ссылаются ли две ссылки на объект на один и тот же экземпляр объекта. Дополнительную информацию см. в <doc:ClassesAndStructures#Identity-Operators>.
Каждый из операторов сравнения возвращает значение типа Bool, чтобы указать, истинно или ложно утверждение:
1 == 1 // true because 1 is equal to 1 2 != 1 // true because 2 isn't 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 <= 1 // false because 2 isn't less than or equal to 1
Операторы сравнения часто используются в условных операторах, таких как оператор 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 см. в ControlFlow.
Вы можете сравнить два кортежа, если они имеют одинаковый тип и количество значений. Кортежи сравниваются слева направо, по одному значению за раз, пока сравнение не найдёт два неравных значения. Эти два значения сравниваются, и результат этого сравнения определяет общий результат сравнения кортежей. Если все элементы равны, то сами кортежи равны. Например:
(1, "zebra") < (2, "apple") // true because 1 is less than 2; "zebra" and "apple" aren't 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 {
answer2
} Вот пример, который вычисляет высоту строки таблицы. Высота строки должна быть на 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
Оператор слияния с nil (a ?? b) распаковывает необязательное значение a, если оно содержит значение, или возвращает значение по умолчанию b, если a имеет значение nil. Выражение a всегда является необязательным типом. Выражение b должно соответствовать типу, хранящемуся внутри a.
Оператор слияния с nil является сокращением для следующего кода:
a != nil ? a! : b
В приведенном выше коде используется тернарный условный оператор и принудительное распаковывание (a!) для доступа к значению, заключённому в a, когда a не является nil, и возвращает b в противном случае. Оператор слияния с nil предоставляет более элегантный способ объединения этого условного проверки и распаковки в лаконичной и читаемой форме.
Примечание: Если значение
aне являетсяnil, значениеbне вычисляется. Это известно как вычисление по короткой цепочке.
В приведенном ниже примере используется оператор слияния с nil для выбора между именем цвета по умолчанию и необязательным именем цвета, определённым пользователем:
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 для рассмотрения его значения. В приведённом выше примере оператор используется для определения начального значения переменной String под названием colorNameToUse. Так как userDefinedColorName имеет значение nil, выражение userDefinedColorName ?? defaultColorName возвращает значение defaultColorName или "red".
Если вы присваиваете ненулевое значение переменной userDefinedColorName и снова выполняете проверку оператора слияния с nil, значение, заключённое в userDefinedColorName, используется вместо значения по умолчанию:
userDefinedColorName = "green" colorNameToUse = userDefinedColorName ?? defaultColorName // userDefinedColorName isn't 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 см. в ControlFlow.
Оператор полуоткрытого диапазона
Оператор полуоткрытого диапазона (a..<b) определяет диапазон от a до b, но не включает b. Он называется полуоткрытым, потому что содержит его начальное значение, но не конечное. Как и в случае с оператором закрытого диапазона, значение a не должно быть больше b. Если значение a равно b, то результирующий диапазон будет пустым.
Полуоткрытые диапазоны особенно полезны при работе со списками с нулевой базой, такими как массивы, где удобно подсчитывать до (но не включая) длины списка:
let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..<count {
print("Person \(i + 1) is called \(names[i])")
}
// Person 1 is called Anna
// Person 2 is called Alex
// Person 3 is called Brian
// Person 4 is called Jack Обратите внимание, что массив содержит четыре элемента, но 0..<count подсчитывает до 3 (индекса последнего элемента массива), потому что это полуоткрытый диапазон. Дополнительные сведения об массивах см. в <doc:CollectionTypes#Arrays>.
Односторонние диапазоны
Оператор закрытого диапазона имеет альтернативную форму для диапазонов, которые продолжаются до тех пор, пока возможно в одном направлении — например, диапазон, который включает все элементы массива с индекса 2 до конца массива. В таких случаях вы можете опустить значение с одной стороны оператора диапазона. Этот вид диапазона называется односторонним, потому что оператор имеет значение только с одной стороны. Например:
for name in names[2...] {
print(name)
}
// Brian
// Jack
for name in names[...2] {
print(name)
}
// Anna
// Alex
// Brian Оператор полуоткрытого диапазона также имеет одностороннюю форму, которая записывается только с его конечным значением. Так же, как при включении значения с обеих сторон, конечное значение не входит в диапазон. Например:
for name in names[..<2] {
print(name)
}
// 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.
Оператор логического НЕ является префиксным оператором и предшествует значению, над которым он выполняется, без пробелов. Его можно прочитать как «не a», как показано в следующем примере:
let allowedEntry = false
if !allowedEntry {
print("ACCESS DENIED")
}
// Prints "ACCESS DENIED" Фраза 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!" Скобки позволяют четко обозначить, что первые два значения рассматриваются как часть отдельного возможного состояния в общей логике. Результат составного выражения не меняется, но общий замысел становится понятнее для читателя. Читабельность всегда предпочтительнее краткости; используйте скобки, когда они помогают прояснить ваши намерения.
This source file is part of the Swift.org open source project
Copyright © 2014 - 2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception