Unetway

Swift - Полные операторы

Swift предоставляет несколько расширенных операторов, которые выполняют более сложные манипуляции со значениями. К ним относятся все побитовые и битовые операторы, с которыми вы будете знакомы из C и Objective-C.

В отличие от арифметических операторов в C, арифметические операторы в Swift по умолчанию не переполняются. Поведение переполнения ловится и сообщается как ошибка. Чтобы включить режим переполнения, используйте второй набор арифметических операторов Swift, которые по умолчанию переполняются, например, оператор сложения переполнения ( &+). Все эти операторы переполнения начинаются с амперсанда ( &).

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

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

Битовые операторы

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

Swift поддерживает все побитовые операторы, найденные в C, как описано ниже.

Побитовый оператор НЕ

Побитовое НЕ оператор ( ~) инвертирует все биты в ряду:

Побитовый оператор NOT является префиксным оператором и появляется непосредственно перед значением, с которым он работает, без пробелов:

let initialBits: UInt8 = 0b00001111

let invertedBits = ~initialBits // equals 11110000

UInt8целые числа имеют восемь битов и могут хранить любое значение между 0и 255. В этом примере UInt8целое число инициализируется двоичным значением 00001111, для которого первые четыре бита установлены 0, а вторые четыре бита установлены 1. Это эквивалентно десятичному значению 15.

Затем побитовый оператор НЕ используется для создания новой константы с именем invertedBits, которая равна initialBits, но со всеми инвертированными битами. Нули становятся единицами, а единицы становятся нулями. Значение invertedBitsis 11110000, которое равно десятичному значению без знака 240.

Побитовое И Оператор

Побитовое И оператор ( &) объединяет биты двух чисел. Он возвращает новый номер, биты которого установлены 1только в том случае, если биты равны 1в обоихвходных числах:

В приведенном ниже примере значения firstSixBitsи lastSixBitsоба имеют четыре средних бита, равных 1. Побитовый оператор И объединяет их, чтобы получить число 00111100, равное десятичному значению без знака 60:

let firstSixBits: UInt8 = 0b11111100

let lastSixBits: UInt8 = 0b00111111

let middleFourBits = firstSixBits & lastSixBits // equals 00111100

Побитовый оператор ИЛИ

Оператор побитового ИЛИ ( |) сравнивает биты двух чисел. Оператор возвращает новый номер, биты которого установлены, 1если биты равны 1в любом входном номере:

В приведенном ниже примере значения someBitsи moreBitsимеют разные биты, установленные на 1. Оператор побитового ИЛИ объединяет их в число 11111110, равное десятичному числу без знака 254:

let someBits: UInt8 = 0b10110010

let moreBits: UInt8 = 0b01011110

let combinedbits = someBits | moreBits // equals 11111110

Побитовый оператор XOR

Оператор побитовое исключающее или «исключающее ИЛИ оператора» ( ^), сравнивает биты двух чисел. Оператор возвращает новый номер, биты которого установлены на то, 1где входные биты различны, и установлены на то, 0где входные биты одинаковы:

В приведенном ниже примере значения firstBitsи для otherBitsкаждого из них установлены биты 1в местоположении, которого нет у другого. Побитовый оператор XOR устанавливает оба этих бита 1в свое выходное значение. Все остальные биты firstBitsи otherBitsсовпадают, и устанавливаются 0в выходное значение:

let firstBits: UInt8 = 0b00010100

let otherBits: UInt8 = 0b00000101

let outputBits = firstBits ^ otherBits // equals 00010001

Побитовые операторы левого и правого сдвига

Оператор побитового сдвига влево ( <<) и оператор побитового сдвига вправо ( >>) перемещают все биты числа влево или вправо на определенное количество мест в соответствии с правилами, определенными ниже.

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

Поведение смещения для целых чисел без знака

Поведение сдвига битов для целых чисел без знака выглядит следующим образом:

  1. Существующие биты перемещаются влево или вправо на требуемое количество мест.
  2. Любые биты, которые перемещаются за пределы целочисленной памяти, отбрасываются.
  3. Нули вставляются в пустые места после того, как исходные биты перемещаются влево или вправо.

Этот подход известен как логический сдвиг .

На рисунке ниже показаны результаты ( смещенные влево по месту) и ( смещенные вправо по месту). Синие числа сдвинуты, серые числа отброшены, и оранжевые нули вставлены:11111111 << 111111111111111111 >> 1111111111

Вот как выглядит сдвиг битов в коде Swift:

let shiftBits: UInt8 = 4 // 00000100 in binary

shiftBits << 1 // 00001000

shiftBits << 2 // 00010000

shiftBits << 5 // 10000000

shiftBits << 6 // 00000000

shiftBits >> 2 // 00000001

Вы можете использовать сдвиг битов для кодирования и декодирования значений в других типах данных:

let pink: UInt32 = 0xCC6699

let redComponent = (pink & 0xFF0000) >> 16 // redComponent is 0xCC, or 204

let greenComponent = (pink & 0x00FF00) >> 8 // greenComponent is 0x66, or 102

let blueComponent = pink & 0x0000FF // blueComponent is 0x99, or 153

В этом примере используется UInt32константа, вызываемая pinkдля хранения значения цвета каскадных таблиц стилей для розового цвета. Значение цвета CSS #CC6699записывается 0xCC6699в виде шестнадцатеричного числа в Swift. Затем этот цвет разлагается на его компоненты red ( CC), green ( 66) и blue ( 99) с помощью оператора побитового оператора AND ( &) и оператора побитового сдвига вправо ( >>).

Красный компонент получается путем выполнения побитового И между числами 0xCC6699и 0xFF0000. Нули в 0xFF0000действительности «маскируют» второй и третий байты 0xCC6699, вызывая 6699их игнорирование и оставляя 0xCC0000в результате.

Затем это число сдвигается на 16 позиций вправо ( ). Каждая пара символов в шестнадцатеричном числе использует 8 битов, поэтому перемещение на 16 позиций вправо преобразуется в . Это так же, как , который имеет десятичное значение .>> 160xCC00000x0000CC0xCC204

Аналогично, зеленый компонент получается путем выполнения побитового И между числами 0xCC6699и 0x00FF00, что дает выходное значение 0x006600. Это выходное значение затем смещается на восемь позиций вправо, давая значение 0x66, которое имеет десятичное значение 102.

Наконец, синий компонент получается путем выполнения побитового И между числами 0xCC6699и 0x0000FF, что дает выходное значение 0x000099. Нет необходимости сдвигать это вправо, так как 0x000099уже равно 0x99, что имеет десятичное значение 153.

Изменение поведения для подписанных целых чисел

Поведение сдвига является более сложным для целых чисел со знаком, чем для целых чисел без знака, потому что целые числа со знаком представлены в двоичном виде. (Приведенные ниже примеры для простоты основаны на 8-разрядных знаковых целых числах, но те же принципы применимы к целым числам со знаком любого размера.)

Целые числа со знаком используют свой первый бит (известный как знаковый бит ), чтобы указать, является ли целое число положительным или отрицательным. Знаковый бит 0означает положительный, а знаковый бит 1означает отрицательный.

Остальные биты (известные как биты значения ) хранят фактическое значение. Положительные числа хранятся точно так же, как и для целых чисел без знака, считая от 0

Знаковый бит 0(означает «положительный»), а семь битов значения - это просто число 4, записанное в двоичной записи.

Отрицательные числа, однако, хранятся по-разному. Они сохраняются путем вычитания их абсолютного значения из 2степени n, где nчисло битов значения. Восьмибитное число имеет семь битов значения, так что это означает 2степень 7или 128.

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

Эта кодировка для отрицательных чисел называется представлением дополнения до двух . Это может показаться необычным способом представления отрицательных чисел, но у него есть несколько преимуществ.

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

 

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

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

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

Операторы переполнения

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

Например, Int16целочисленный тип может содержать любое целое число со знаком между -32768и 32767. Попытка установить Int16константу или переменную в число вне этого диапазона вызывает ошибку:

var potentialOverflow = Int16.max

// potentialOverflow equals 32767, which is the maximum value an Int16 can hold

potentialOverflow += 1

// this causes an error

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

Однако, если вы хотите, чтобы условие переполнения урезало количество доступных битов, вы можете включить это поведение, а не вызывать ошибку. Swift предоставляет три арифметических оператора переполнения, которые выбирают поведение переполнения для целочисленных вычислений. Все эти операторы начинаются с амперсанда ( &):

  • Добавление переполнения ( &+)
  • Вычитание переполнения ( &-)
  • Переполнение умножения ( &*)

Переполнение значения

Числа могут переполняться как в положительном, так и в отрицательном направлении.

Вот пример того, что происходит, когда целое число без знака может переполняться в положительном направлении, используя оператор сложения переполнения ( &+):

var unsignedOverflow = UInt8.max

// unsignedOverflow equals 255, which is the maximum value a UInt8 can hold

unsignedOverflow = unsignedOverflow &+ 1

// unsignedOverflow is now equal to 0

Переменная unsignedOverflowинициализируется с максимальным значением, которое UInt8может содержать ( 255или 11111111в двоичном виде). Затем он увеличивается с 1помощью оператора сложения переполнения ( &+). Это увеличивает его двоичное представление только на размер, который UInt8может содержать a , вызывая его переполнение за его пределы, как показано на диаграмме ниже. Значение, которое остается в границах UInt8после добавления переполнения 00000000, равно нулю.

Нечто подобное происходит, когда целое число без знака может переполниться в отрицательном направлении. Вот пример использования оператора вычитания переполнения ( &-):

var unsignedOverflow = UInt8.min

// unsignedOverflow equals 0, which is the minimum value a UInt8 can hold

unsignedOverflow = unsignedOverflow &- 1

// unsignedOverflow is now equal to 255

Минимальное значение, которое UInt8может содержать a, равно нулю или 00000000в двоичном виде. Если вы вычли 1из 00000000использования оператора вычитания переполнения ( &-), число будет переполнено и будет округлено до 11111111или 255в десятичном виде.

Переполнение также происходит для целых чисел со знаком. Все сложение и вычитание для целых чисел со знаком выполняется поразрядным образом, причем знаковый бит включается как часть чисел, которые добавляются или вычитаются.

var signedOverflow = Int8.min

// signedOverflow equals -128, which is the minimum value an Int8 can hold

signedOverflow = signedOverflow &- 1

// signedOverflow is now equal to 127

Минимальное значение, которое Int8может содержать -128, или 10000000в двоичном виде. Вычитание 1из этого двоичного числа с помощью оператора переполнения дает двоичное значение 01111111, которое переключает бит знака и дает положительное 127максимальное положительное значение, которое Int8может содержать.

Как для целых чисел со знаком, так и для без знака переполнение в положительном направлении оборачивается от максимального действительного целочисленного значения обратно к минимуму, а переполнение в отрицательном направлении - от минимального значения до максимального.

Приоритетность и ассоциативность

Приоритет оператора дает некоторым операторам более высокий приоритет, чем другим; эти операторы применяются в первую очередь.

Ассоциативность операторов определяет, как операторы с одинаковым приоритетом группируются вместе - либо слева, либо справа. Думайте об этом как о значении «они ассоциируются с выражением слева от них» или «они ассоциируются с выражением справа».

При определении порядка вычисления составного выражения важно учитывать приоритет каждого оператора и его ассоциативность. Например, приоритет оператора объясняет, почему следующее выражение равно 17.

2 + 3 % 4 * 5

// this equals 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, включая полный список групп приоритетов операторов и параметров ассоциативности .

ЗАМЕТКА

Приоритеты операторов Свифта и правила ассоциативности проще и более предсказуемы, чем в C и Objective-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экземпляров, которые добавляются вместе.

Метод type может использоваться как инфиксный оператор между существующими Vector2Dэкземплярами:

let vector = Vector2D(x: 3.0, y: 1.0)

let anotherVector = Vector2D(x: 2.0, y: 4.0)

let combinedVector = vector + anotherVector

// combinedVector is a Vector2D instance with values of (5.0, 5.0)

В этом примере складываются векторы и получается вектор: (3.0, 1.0)(2.0, 4.0)(5.0, 5.0)

Префиксные и постфиксные операторы

Приведенный выше пример демонстрирует пользовательскую реализацию бинарного инфиксного оператора. Классы и структуры также могут предоставлять реализации стандартных унарных операторов . Унарные операторы работают на одну цель. Они являются префиксными, если они предшествуют своей цели (например, -a), и постфиксными операторами, если они следуют своей цели (например, b!).

Вы реализуете префиксный или постфиксный унарный оператор, написав модификатор prefixor 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 is a Vector2D instance with values of (-3.0, -4.0)

let alsoPositive = -negative

// alsoPositive is a Vector2D instance with values of (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 now has values of (4.0, 6.0)

ЗАМЕТКА

Невозможно перегрузить оператор присваивания по умолчанию ( =). Только составные операторы присваивания могут быть перегружены. Аналогично, троичный условный оператор ( ) не может быть перегружен.a ? b : c

Операторы эквивалентности

По умолчанию пользовательские классы и структуры не имеют реализации операторов эквивалентности , известных как равные operator ( ==) и не равныеoperator ( !=). Обычно вы реализуете ==оператор и используете стандартную реализацию !=оператора по умолчанию, которая сводит на нет результат ==оператора. Существует два способа реализации ==оператора: вы можете реализовать его самостоятельно, или для многих типов вы можете попросить Swift синтезировать реализацию для вас. В обоих случаях вы добавляете соответствие стандартному 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("These two vectors are equivalent.")

}

// Prints "These two vectors are equivalent."

Во многих простых случаях вы можете попросить Swift предоставить вам синтезированные реализации операторов эквивалентности. Swift предоставляет синтезированные реализации для следующих типов пользовательских типов:

  • Структуры, которые имеют только сохраненные свойства, соответствующие Equatableпротоколу
  • Перечисления, имеющие только связанные типы, соответствующие Equatableпротоколу
  • Перечисления, которые не имеют связанных типов

Чтобы получить синтезированную реализацию ==, объявите Equatableсоответствие в файле, который содержит исходное объявление, без ==самостоятельной реализации оператора.

Пример ниже определяет Vector3Dструктуру для трехмерного вектора положения , подобную структуре. Поскольку , и свойства являются все из типа, получает синтезируются реализации операторов эквивалентности.(x, y, z)Vector2DxyzEquatableVector3D

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.")

}

// Prints "These two vectors are also equivalent."

Таможенные операторы

Вы можете объявить и реализовать свои собственные пользовательские операторы в дополнение к стандартным операторам, предоставляемым Swift. Новые операторы объявляются на глобальном уровне с помощью operatorключевого слова и помечаются модификаторами prefixinfixили 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 now has values of (2.0, 8.0)

// afterDoubling also has values of (2.0, 8.0)

Приоритет для пользовательских инфиксных операторов

Каждый пользовательский инфиксный оператор принадлежит к группе приоритетов. Группа приоритетов определяет приоритет оператора относительно других инфиксных операторов, а также ассоциативность оператора.

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

В следующем примере определяется новый пользовательский инфиксный оператор под названием +-, который принадлежит к группе приоритетов 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 is a Vector2D instance with values of (4.0, -2.0)

Этот оператор складывает xзначения двух векторов и вычитает yзначение второго вектора из первого. Поскольку по сути это «аддитивный» оператор, ему была назначена та же группа приоритетов, что и у аддитивных инфиксных операторов, таких как +и -. Для получения информации об операторах, предоставляемых стандартной библиотекой Swift, включая полный список групп приоритетов операторов и параметров ассоциативности. Для получения дополнительной информации о группах приоритетов и для просмотра синтаксиса для определения ваших собственных операторов и групп приоритетов.

ЗАМЕТКА

Вы не указываете приоритет при определении префиксного или постфиксного оператора. Однако если к одному и тому же операнду применить оператор префикса и постфикса, сначала применяется оператор постфикса.