Разное

Operator swift: Swift.org — Not Found

Содержание

Условная конструкция If. Тернарный оператор

Условная конструкция If. Тернарный оператор

Последнее обновление: 29.12.2017

В языках программирования часто бывает необходимо произвести некоторые действия в зависимости от выполнения тех или иных условий. Если определенные условия
соблюдаются, то выполнить одни действия, если не соблюдаются, то выполнить другие. И для в языках программирования применяются условные конструкции. Рассмотрим,
какие условные конструкции есть в языке Swift.

Конструкция if/else

Конструкция if проверяет истинность некоторого условия и в зависимости от результатов проверки выполняет определенный код:


if условие {
	// набор действий
}

Например:


let num1 = 22
let num2 = 15
if num1 > num2{
	
	print("num1 больше чем num2")
}

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

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


let num1 = 22
let num2 = 15
if num1{
	
	print("num1 больше чем num2")
}

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


let num1 = 22
let num2 = 15
if num1 > num2{
	
	print("num1 больше чем num2")
}
else{
	print("num1 меньше чем num2")
}

Но при сравнении чисел мы можем насчитать три состояния: первое число больше второго, первое число меньше второго и числа равны. Используя конструкцию
else if, мы можем обрабатывать дополнительные условия:


let num1 = 22
let num2 = 15
if num1 > num2{
	
	print("num1 больше чем num2")
}
else if (num1 < num2){

    print("num1 меньше чем num2")
}
else{

    print("num1 и num2 равны")
}

Тернарный оператор

Тернарный оператор аналогичен простой конструкции if и имеет следующий синтаксис:

[первый операнд - условие] ? [второй операнд] : [третий операнд]

В зависимости от условия тернарный оператор возвращает второй или третий операнд: если условие равно true, то возвращается второй операнд; если условие
равно false, то третий. Например:


var num1 = 10
var num2 = 6
var num3 = num1 > num2 ? num1 - num2 : num1 + num2

В данном случае num3 будет равно 4, так как num1 больше num2, поэтому будет выполняться второй операнд: num1 - num2.

Сохранение логики фильтрации в Swift Combine. Часть 2 / Блог компании OTUS / Хабр

Дата-ориентированный Combine


Перевод статьи подготовлен специально для студентов продвинутого курса «iOS Разработчик».


В предыдущем эпизоде мы успешно смоделировали поток значений, где к каждому значению был привязан один простой оператор (delay).

В этой части мы рассмотрим еще несколько операторов, сделаем их Codeable и, наконец, преобразуем их в паблишер Combine во время выполнения.


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

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

Сайт ReactiveX разбивает их примерно на 10 категорий: создание, трансформация, фильтрация, объединение, обработка ошибок, вспомогательные, условные, математические/агрегатные, backpressure, connectable-observable и операторы для преобразования observable (To). Если вам интересно, у ReactiveX есть хорошее объяснение для каждого типа и оператора.

Примечание: Если вы не знакомы с RxSwift, Observable в RxSwift эквивалентен Publisher в Combine.

В предыдущей части мы упомянули оператор delay, который относится к вспомогательному (utility) типу. Сегодня мы сосредоточимся на сохранении двух фильтрационных (filtering) операторов.


Операторы фильтрации

Этот тип оператора препятствует всем или некоторым (или никаким) из элементов потока продвигаться дальше по потоку на основе данного условия.

dropFirst

dropFirst останавливает передачу первых n элементов. Мы можем просто добавить его в наше перечисление (enum) Operator, учитывая его простоту.

enum Operator {
 case delay(seconds: Double)
 case dropFirst(count: Int)
}

Мы также можем легко преобразовать этот кейс перечисления в Publisher.

extension Operator {func applyPublisher<T>(_ publisher: AnyPublisher<T, Never>) -> AnyPublisher<T, Never> { 
switch self {
   case .dropFirst(let count):
       return publisher.dropFirst(count).eraseToAnyPublisher()
 // пропустим остальные кейсы
 }}}

Теперь оператор dropFirst можно сохранить и отобразить в списке операторов.

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

Filter

В отличие от dropFirst, который имеет очень простые критерии фильтрации, оператор filter использует замыкание (closure) вместо примитивного типа. Это уже случай посложнее. Как мы сохраняем и распространяем замыкание?

filter(_:)

Повторно публикует все элементы, которые соответствуют заданному замыканию.

developer.apple.com

Давайте рассмотрим метод filter поближе.

func filter(_ isIncluded: @escaping (Self.Output) -> Bool) -> Publishers.Filter<Self>

Его замыкание isIncluded принимает универсальный тип и возвращает логическое значение.

Есть ли в Foundation что-то, что представляет логические условия и возвращает логическое значение? Напоминает что-нибудь?

Filter с NSPredicate

Ответ — NSPredicate. Если мы можем сохранить условия фильтрации в виде выражений в строковом формате, мы можем просто передать значение потока и использовать NSPredicate для оценки результатов.

Давайте продолжим и добавим filter в перечисление.

enum Operator {
 case delay(seconds: Double)
 case dropFirst(count: Int)
 case filter(expression: String)
}

Все, что нам нужно, это фильтровать выражения типа %d !=3 или %@ != “D”; следовательно, expression является соответствующим типом. Точно так же мы должны быть в состоянии переместить перечисление filter в Publisher.

extension Operator {
func applyPublisher<T>(_ publisher: AnyPublisher<T, Never>) -> AnyPublisher<T, Never> { 
 switch self {
   case .filter(let expression):
   return publisher.filter { value in
               NSPredicate(format: expression,
                           argumentArray: [value])
                .evaluate(with: nil) }.eraseToAnyPublisher()
      
     // пропустим остальные кейсы
 }}}

Как и планировалось, мы отправляем выражение в NSPredicate вместе со значением, отправляемым из Publisher.

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

Как вы можете наблюдать, Filter Stream добавляется в этот сохраненный массив операторов и преобразуется в Publisher, чтобы отфильтровать число 3 из вышестоящих значений.


В следующем эпизоде: Сохраняем операторы трансформации, Map и Scan

В GIF-демо вы можете обнаружить, что список операторов довольно пуст. В ближайшие несколько недель мы собираемся заполнить его различными типами операторов: операторами трансформации, map и scan.
Вы можете найти исходный код в этом combine-magic-swifui репозитории в папке combine-playground.

Ждем ваши комментарии и приглашаем на день открытых дверей по курсу.

Оператор возведения в степень в Swift

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

Действительно ли в языке нет предопределенного целочисленного или плавающего оператора возведения в степень?

swift

exponentiation

Поделиться

Источник


mcgregor94086    

05 июня 2014 в 16:46

9 ответов




92

Там нет оператора, но вы можете использовать функцию pow следующим образом:

return pow(num, power)

Если вы хотите, вы также можете заставить оператора вызвать функцию pow следующим образом:

infix operator ** { associativity left precedence 170 }

func ** (num: Double, power: Double) -> Double{
    return pow(num, power)
}

2.0**2.0 //4.0

Поделиться


Connor    

05 июня 2014 в 16:57



24

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

let x = 2 << 0    // 2
let y = 2 << 1    // 4
let z = 2 << 7    // 256

Обратите внимание, что значение ‘power’ на 1 меньше, чем вы могли бы подумать.

Обратите внимание, что это быстрее, чем pow(2. 0, 8.0) , и позволяет избежать использования двойников.

Поделиться


chanceoperation    

22 февраля 2015 в 23:16



13

Для тех, кто ищет версию Swift 3 оператора инфикса ** :

precedencegroup ExponentiationPrecedence {
  associativity: right
  higherThan: MultiplicationPrecedence
}

infix operator ** : ExponentiationPrecedence

func ** (_ base: Double, _ exp: Double) -> Double {
  return pow(base, exp)
}

func ** (_ base: Float, _ exp: Float) -> Float {
  return pow(base, exp)
}

2.0 ** 3.0 ** 2.0    // 512
(2.0 ** 3.0) ** 2.0  // 64

Поделиться


reitermarkus    

11 января 2017 в 02:19




5

Я сделал это так:

operator infix ** { associativity left precedence 200 }

func ** (base: Double, power: Double) -> Double {
    return exp(log(base) * power)
}

Поделиться


ldanilek    

24 июня 2014 в 20:22



3

Его нет, но у вас есть функция pow .

Поделиться


Rod    

05 июня 2014 в 16:54



2

Если вас особенно интересует оператор возведения в степень для типа Int , я не думаю, что существующие ответы будут особенно хорошо работать для больших чисел из-за того, как числа с плавающей запятой представлены в памяти. При преобразовании в Float или Double из Int , а затем обратно (что требуется функциями pow , powf и powl в модуле Darwin ) вы можете потерять точность . Вот точная версия для Int :

let pow = { Array(repeating: $0, count: $1). 60000 или...
		


У Bigdecimal Возведения В Степень

Я создаю пользовательский класс BigDecimal (для практики и от скуки) и имею пользовательские алгоритмы сложения, вычитания, умножения и деления, и я хотел бы сделать функцию для возведения в...


Оператор возведения в степень для Булева числа в JavaScript?

См. это , exponentiation operator возвращает результат возведения первого операнда в степень второго операнда, как оператор возведения в степень в Python, который является частью предложения...


Использование ` * * 'в качестве оператора возведения в степень в swift неправильно работает с оператором' - `

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


Могу ли я запрограммировать оператор возведения в степень в C++?

В численном программировании я часто хочу поднять число до степени внутри выражения. Это приводит к коду, который имеет сотни вхождений pow(x,2) или что-то в этом роде. Это загромождает код и делает...


Что такое оператор возведения в степень ** в php?

Может ли кто-нибудь сказать, что делает оператор возведения в степень ** в php ? Примеры будут более полезны. Спасибо


JavaScript проектное решение унарного оператора возведения в степень

Итак, я дурачился с новым оператором возведения в степень и обнаружил, что вы не можете поставить унарный оператор непосредственно перед базовым числом. let result = -2 ** 2; // syntax error let...


Функция возведения в степень Haskell

Как получить функцию возведения в степень в церковных цифрах с помощью Haskell? Я пытаюсь применить правило, которое λxy.yx, но что-то не работает правильно. exponentiation :: (Num a) => Func a...


Почему Python ` * * 'используется для возведения в степень вместо оператора'^'?

Почему ^ не квадрат в Python? Я знаю, что вместо возведения в степень используется ** , но что именно такое ^ и почему вместо этого не использовался этот оператор? Например, 2^2=0 , 3^2=1 .

Оператор switch в Swift: синтаксис и примеры использования

Оператор swich позволяет проверить определенное значение и сравнить его с несколькими условиями. Это особенно эффективно для принятия решений на основе переменной, которая может содержать ряд возможных значений. Использование оператора switch позволяет использовать более краткий и удобный синтаксис кода.

Что из себя представляет оператор switch?

Оператор switch проверяет значение и сравнивает его с несколькими возможными шаблонами.

Рассмотрим следующее перечисление:

enum Compass {
    case north
    case east
    case south
    case west
}

Если вы хотите найти нужное направление, вы можете использовать следующий код:

let heading = Compass.south
 
if heading == .north {
    print("Вы направляетесь на север!")
} else if heading == .east {
    print("Вы направляетесь на восток!")
} else if heading == .south {
    print("Вы направляетесь на юг!")
} else if heading == .west {
    print("Вы направляетесь на запад!")
}

Приведенный выше код использует оператор if для оценки значения heading и вывода соответствующей строки текста.

Мы можем сделать то же самое, используя оператор switch:

switch heading {
case .north:
    print("Вы направляетесь на север!")
case .east:
    print("Вы направляетесь на восток!")
case .south:
    print("Вы направляетесь на юг!")
case .west:
    print("Вы направляетесь на запад!")
}

Сначала мы используем ключевое слово switch, а затем проверяемое выражение, в данном случае это константа heading. Это значение, которое рассматривается блоками switch. Затем мы перебираем возможные варианты значений с помощью case. В приведенном выше примере мы рассматриваем все возможные значения перечисления Compass.

Особенностью switch является то, что каждый switch блок должен быть исчерпывающим. Посмотрите, что происходит, когда мы забываем включить вариант с .east:

switch heading {
case . north:
    print("Вы направляетесь на север!")
case .south:
    print("Вы направляетесь на юг!")
case .west:
    print("Вы направляетесь на запад!")
}
 
// error: switch must be exhaustive

Особенности работы с оператором switch

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

Рассмотрим перечисление Authorization:

enum Authorization {
    case granted
    case undetermined
    case unauthorized
    case denied
    case restricted
}

Если вы хотите предоставить пользователю доступ к ресурсу в зависимости от его состояния авторизации, вы можете сделать это:

switch state {
case .granted:
    print("Доступ разрешен.")
default:
    print("Доступ закрыт!")
}

В приведенном выше коде парамтер default используется для ответа на любой необработанный случай. Это делает выражение со switch исчерпывающим.

Вы также можете проверить более сложные случаи:

switch state {
case .granted:
    print("Доступ разрешен.")
case .undetermined:
    print("Предоставьте код доступа.")
case .unauthorized, .denied, .restricted:
    print("Доступ закрыт!")
}

Последний случай объединяет несколько случаев в одной строке.

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

var message = "Ответ: "
let state = Authorization.undetermined
 
switch state {
case .granted:
    message += "Доступ открыт. Вы можете продолжить"
case .undetermined:
    message += "Предоставьте код доступа."
    fallthrough
default:
    message += "Доступ закрыт!"
}
 
print(message)
// Output: Ответ: Предоставьте код доступа. Доступ закрыт!

В приведенном выше примере выполняется как условие .undetermined, так и default.

Проверка диапазонов с помощью switch

Вы можете использовать операторы switch для проверки интервалов и диапазонов.

Рассмотрим, например, как люди воспринимают видимый свет с разными длинами волн:

let wavelength = 620
 
switch wavelength {
case 380. .<450:
    print("Пурпурный!")
case 450..<495:
    print("Синий!")
case 495..<570:
    print("Зеленый!")
case 570..<590:
    print("Желтый!")
case 590..<620:
    print("Оранжевый!")
case 620..<750:
    print("Красный!")
default:
    print("Не видимый спектр!")
}

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

Оператор switch и кортежи

Вы можете использовать оператор switch с кортежами.

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

let flight = (747, "SFO")

Тип константы flight (Int, String). После определения кортежа вы не можете изменить его порядок или тип. Кортежи идеально подходят для передачи нескольких связанных значений в одну переменную.

Вы можете получить доступ к значениям кортежа с помощью индекса:

print(flight.1)
// Output: SFO

Также можно использовать значения кортежа:

let flight = (airplane: 747, airport: "SFO")
print(flgith.airplane)
// Output: 747

Мы можем использовать кортежи вместе с оператором switch:

for i in 1...100 {
    switch (i % 3 == 0, i % 5 == 0) {
    case (true, false):
        print("Fizz")
    case (false, true):
        print("Buzz")
    case (true, true):
        print("FizzBuzz")
    default:
        print(i)
    }
}

В приведенном выше коде мы создаем кортеж из двух значений: результат вычисления i % 3 == 0 и результат вычисления i % 5 == 0. Теперь мы можем учитывать различные значения кортежей: (true, false), (false, true), (true, true). Если ни один из этих случаев не совпадает, мы выводим значение i.

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

let airplane = (type: "737-800", heading: "LAX")
 
switch airplane {
case ("737-800", _):
    print("Этот самолет модели 737-800.")
case (let type, "LAX"):
    print("Этот \(type) летит в аэропорт Лос-Анджелеса. ")
default:
    print("Неизвестный самолет.")
}
 
// Этот самолет модели 737-800.

В приведенном выше коде мы отвечаем 3 разных случая.

Выражение let type называется связыванием значения. Это позволяет нам привязать значение кортежа к константе. Теперь внутри case блока вы можете использовать эту константу, например, распечатать ее.

Использование switch с where

Мы также можем использовать switch с оператором where:

enum Response {
    case error(Int, String)
    case success
}
 
let httpResponse = Response.success
 
switch httpResponse {
case .error(let code, let status) where code > 399:
    print("HTTP Ошибка: \(code) \(status)")
case .error:
    print("HTTP запрос неуспешен")
case .success:
    print("HTTP запрос успешен")
}
 
// HTTP запрос успешен

В приведенном коде происходят две вещи:

  • Мы создаем перечисление Response, которое имеет два случая: .error и .success. Случай .error имеет два соответствующие значения: целое число и строку.
  • Мы оцениваем значение httpResponse с помощью оператора switch, реагируя на разные значения перечисления Response.

Если мы изменим значение httpResponse:

let httpResponse = Response.error(404, "Not Found")
// HTTP Ошибка: 404 Not Found

Или:

let httpResponse = Response.error(301, "Moved Permanently")
// HTTP запрос неуспешен

Есть еще один .error случай, который нас особенно интересует, а именно код ошибки, который больше, чем 399.

Коды состояния HTTP, которые используются в интернете, указывают на то, что коды состояния от 400 и выше являются ошибками клиента и сервера. Иными словами, когда вы получаете один из них, что-то пошло не так.

В приведенном выше коде мы используем привязку значений для констант code и status соответствующих значений перечисления Response. Мы также используем ключевое слово where, чтобы указать, что этот случай должен выполняться для любого значения code, превышающего 399.

Swift Операторы

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

Swift предоставляет следующие операторы:

  • Арифметические операторы
  • сравнение
  • Логические операторы
  • Битовые операторы
  • Операторы присваивания
  • Интервальные Операторы
  • Другие операторы

В этой главе мы объясним вам арифметические операторы, операторы сравнения, логические операторы, операторы побитового, оператор присваивания и других операторов.


Арифметические операторы

В следующей таблице перечислены Swift арифметические операторы поддержки языка, 10 из которых переменная переменная B 20:

операторы описание примеров
+ плюс Результаты поиска по запросу A + B 30
- минус A - результаты B -10
* Умножение знак А результаты * B для 200
/ Знак деления B / A 2 результатов
% остаток В результате% А 0
++ инкремент A ++ 11 результатов
- декремент A-- результат 9

примеров

Ниже приведен простой пример арифметических операций:

import Cocoa

var A = 10
var B = 20

print("A + B 结果为:\(A + B)")
print("A - B 结果为:\(A - B)")
print("A * B 结果为:\(A * B)")
print("B / A 结果为:\(B / A)")
A++
print("A++ 后 A 的值为 \(A)")
B--
print("B-- 后 B 的值为 \(B)")

Приведенные выше результаты выполнения программы:

A + B 结果为:30
A - B 结果为:-10
A * B 结果为:200
B / A 结果为:2
A++ 后 A 的值为 11
B-- 后 B 的值为 19

сравнение

В следующей таблице перечислены операторы сравнения Swift языковую поддержку, в которой переменные A 10, B 20 переменных:

операторы описание примеров
== равных (A == B) является ложным.
! = Не равно (A! = B) истинно.
> Более (A> B) неверно.
< Менее (A <B) истинно.
> = Больше или равно (A> = B) является ложным.
<= Меньше или равно (A <= B) является истинным.

примеров

Ниже приведен простой пример операций сравнения:

import Cocoa

var A = 10
var B = 20

print("A == B 结果为:\(A == B)")
print("A != B 结果为:\(A != B)")
print("A > B 结果为:\(A > B)")
print("A < B 结果为:\(A < B)")
print("A >= B 结果为:\(A >= B)")
print("A <= B 结果为:\(A <= B)")

Приведенные выше результаты выполнения программы:

A == B 结果为:false
A != B 结果为:true
A > B 结果为:false
A < B 结果为:true
A >= B 结果为:false
A <= B 结果为:true

Логические операторы

В следующей таблице перечислены поддержки Swift язык логических операторов, где переменная А истинно, то переменная B является ложным:

операторы описание примеров
&& Логика и. Если оператор TRUE, обе стороны было TRUE. (A && B) является ложным.
|| Или логика. Если оператор с обеих сторон, по крайней мере один из Тру значение TRUE. (A || B) истинно.
! Логическое НЕ. Это инвертирует логическое значение, так верно становится ложным, ложное становится истинным. ! (A && B) истинно.

Ниже приведен простой пример логической операции:

import Cocoa

var A = true
var B = false

print("A && B 结果为:\(A && B)")
print("A || B 结果为:\(A || B)")
print("!A 结果为:\(!A)")
print("!B 结果为:\(!B)")

Приведенные выше результаты выполнения программы:

A && B 结果为:false
A || B 结果为:true
!A 结果为:false
!B 结果为:true

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

Битовые операторы битов, используемых для работы, ~, &, |, ^ были сведены на нет, а бит, или битом и, побитовое исключающее ИЛИ операции со следующими примерами таблицы:

р Q р & д р | д р ^ д
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

Если A = 60 и B = 13, две переменные, соответствующие двоичном виде:

A = 0011 1100

B = 0000 1101

Для битовых операций:

операторы описание диаграмма примеров
& Побитовое и. = A
print("C 结果为:\(C)")

C |= A
print("C 结果为:\(C)")
*/

Приведенные выше результаты выполнения программы:

C 结果为:30
C 结果为:40
C 结果为:30
C 结果为:300
C 结果为:30

Интервальные Операторы

Swift предлагает два оператора диапазона.

операторы описание примеров
Операторы замкнутый интервал Закрытый интервал оператор (а ... б) определенный интервал содержит все значения от а до Ь (в том числе и б), Ь должно быть больше или равно а. Закрытый интервал оператор итерации в диапазоне всех значений очень полезен, так как в наличии для цикла: 1 ... 5 Диапазон 1, 2, 3, 4 и 5
Интервал оператор Полуоткрытая Полуоткрытый интервал (а .. 1 .. <5 интервал значение 1, 2, 3, и 4

Ниже приведен простой пример интервальной арифметики:

import Cocoa

print("闭区间运算符:")
for index in 1...5 {
    print("\(index) * 5 = \(index * 5)")
}

print("半开区间运算符:")
for index in 1..<5 {
    print("\(index) * 5 = \(index * 5)")
}

Приведенные выше результаты выполнения программы:

闭区间运算符:
1 * 5 = 5
2 * 5 = 10
3 * 5 = 15
4 * 5 = 20
5 * 5 = 25
半开区间运算符:
1 * 5 = 5
2 * 5 = 10
3 * 5 = 15
4 * 5 = 20

Другие операторы

Swift предлагает другие типы операторов, таких как моно-, ди-, и оператор троичного.

  • Унарные операторы на манипуляции одной операционной объекта (например , -a ). Унарный оператор минут до и после операторы, операторы должны предварительно работающие непосредственно перед объектом (например, !b ), Сзади оператора на операцию сразу после объекта (например , как i++ ).
  • Бинарные операторы работают обе операционные объекты (такие , как 2 + 3 ), то в доме, так как они появляются между двумя операндами.
  • Три тернарный оператор работает цель операции, и C языки, Swift является лишь тернарный оператор, является тернарный оператор ( a ? b : c ).
операторы описание примеров
Унарный минус Добавить цифровой фронт - префикс -3 Или -4
Унарный плюс Digital Money Добавить + код +6 Результат 6
троичный оператор ? Условие X: Y Если вы добавляете верно, то значение X, иначе Y

Ниже приведен один доллар, простой пример двойных и тройных операций:

import Cocoa

var A = 1
var B = 2
var C = true
var D = false
print("-A 的值为:\(-A)")
print("A + B 的值为:\(A + B)")
print("三元运算:\(C ? A : B )")
print("三元运算:\(D ? A : B )")

Приведенные выше результаты выполнения программы:

-A 的值为:-1
A + B 的值为:3
三元运算:1
三元运算:2

Оператор Внеочередные

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

Приоритет в порядке убывания сверху вниз, верхний имеет самый высокий приоритет, оператор запятая имеет самый низкий приоритет.

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

Основные приоритеты должны помнить:

  • Оптимальный указатель, унарный, чем бинарные операторы. = | =
Справа налево
запятая , Слева направо

Ниже приведен простой пример оператора старшинства:

import Cocoa

var A = 0

A = 2 + 3 * 4 % 5
print("A 的值为:\(A)")

Приведенные выше результаты выполнения программы:

A 的值为:4

Примеры анализа:

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

2 + ((3 * 4) % 5)

Первый шаг при расчете: (3 * 4) = 12, так что выражение эквивалентно:

2 + (12 % 5)

Второй шаг, чтобы вычислить 12% 5 = 2, поэтому данное выражение эквивалентно:

2 + 2

На данный момент можно легко увидеть, что расчетные результаты четырех.

Guard — зачем же он нужен? – @IBLog

Вы читаете перевод статьи Эрика Керни

Когда я впервые увидел оператор guard во время Apple’s Platform State of the Union, я не мог до конца понять, зачем бы я стал им пользоваться и что же он из себя представляет? Вот короткое описание:

Как и оператор if, guard исполняет код полагаясь на логическое значение выражения. В отличии от if, guard исполняет код только при получении false. Можно думать о нём как об Assert, только программа не будет завершена.

Вливаемся

Возьмём простой пример для сравнения старой техники и использования guard:

func fooManualCheck(x: Int?) {
    if x == nil || x <= 0 {
        // Условия не соблюдены, выходим из функции
        return
    }
    
    // Работаем с x
    x!.description
}

Это самый простой способ (в стиле Objective-C) убедиться, что значение существует и удовлетворяет условию. Хотя, работает оно прекрасно, в нём есть несколько недостатков:

  1. Мы проверяем условие, которое нам не нужно, вместо проверки значения, которое нас интересует. Код становится очень запутанным, если у нас несколько таких проверок. Мы ведь надеемся, что наше условие на самом деле не пройдёт.
  2. Так же нужно “силой развернуть” (force unwrap) опциональное значение.

Swift представил нам более чистый способ сделать это и избавил нас от этих недостатков с помощью Optional Binding:

func fooBinding(x: Int?) {
    if let x = x where x > 0 {
        // Работаем с x
        x.description
    }
    
    // Условия не соблюдены, выходим из функции
}

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

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

И тут на помощь приходит guard:

func fooGuard(x: Int?) {
    guard let x = x where x > 0 else {
        // Условия не соблюдены, выходим из функции
        return
    }
    
    // Работаем с x
    x.description
}

Использование guard решает все 3 проблемы, упомянутые выше:

  1. Идёт проверка условий, которые нам действительно важны. Если условие не соблюдено, запускается блок else, который обязательно выводит из функции. Если вы забудете постаивть return, компилятор сообщит вам об ошибке.
  2. Если условие соблюдено, опциональная переменная автоматически развёрнута и доступна внутри guard.
  3. Мы проверяем условия рано и функция будет просто читаема.

Классно ещё то, что это работает и для не-опциональных значений:

func fooNonOptionalGood(x: Int) {
    guard x > 0 else {
        // Условия не соблюдены, выходим из функции
        return
    }
    
    // Работаем с x
}
 
func fooNonOptionalBad(x: Int) {
    if x <= 0 {
        // Условия не соблюдены, выходим из функции
        return
    }
    
    // Работаем с x
}

Сворачиваемся

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

swift - Двоичный оператор '===' не может применяться к операндам типа 'Any?' и UIBarButtonItem!

Следующий код раньше позволял компилировать в swift 2.2, а не в swift 3.0. Как это исправить?

Ошибка: двоичный оператор '===' нельзя применить к операндам типа 'Any?' и UIBarButtonItem!

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if sender === saveButton { // Error!
        // ... 
    } else if sender === closeButton { // Error!
        // ...
    }
}

27

Yuchen Zhong

18 Сен 2016 в 00:31

2 ответа

Лучший ответ

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

Попробуй это:

if sender as AnyObject? === saveButton {

(То же самое для другого сравнения sender.)

И помните, что в Swift 3 as AnyObject стало одной из самых рискованных операций, вам не следует использовать as AnyObject в других случаях.

49

OOPer
17 Сен 2016 в 21:42

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

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let sender = sender as? UIBarButtonItem, sender === saveButton {
        // . ..
    } else if let sender = sender as? UIBarButtonItem, sender === closeButton {
        // ...
    }
}

13

vacawama
17 Сен 2016 в 21:45

39551937

Операторы Swift (с примерами)

Операторы - это специальные символы (символы), которые выполняют операции с операндами (переменными и значениями). Некоторые базовые операции включают присвоение, изменение, объединение и проверку значений.

Например, + - оператор, выполняющий сложение.

В статье о переменных и константах Swift вы узнали о переменных / константах. Теперь в этой статье вы познакомитесь с их операторами.


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

Операторов можно разделить на две основные категории на основе:

  1. Количество операндов
  2. Операция оператора

В соответствии с числом операндов , с которыми работает оператор, операторов можно разделить на:

1.Унарный оператор

Эти операторы работают с одним операндом.

Пример 1: Унарный оператор

  печать (! Правда)
var a = -5
печать (-a)
  

Когда вы запустите вышеуказанную программу, вывод будет:

  ложь
5  

2. Бинарный оператор

Этот оператор работает с двумя операндами.

Пример 2: Бинарный оператор

  пусть результат = 20 + 30
печать (результат)
  

Когда вы запустите вышеуказанную программу, вывод будет:

  50  

3.Тернарные операторы

Этот оператор оперирует тремя операндами. Посетите Swift Ternary Conditional Operator, чтобы узнать о нем больше.

Пример 3: Тернарный оператор

  пусть результат = (5> 10)? «Значение больше»: «Значение меньше»
печать (результат)
  

Когда вы запустите вышеуказанную программу, вывод будет:

  Меньшее значение  

В соответствии с операцией , которую выполняет оператор , ее можно разделить на:

1.

= побитовое исключающее ИЛИ и оператор присваивания | = побитовое включающее ИЛИ и оператор присваивания

Пример 4: Обычный оператор присвоения

  лет, возраст = 10
let platform = "iOS"
печать (возраст)
печать (платформа)
  

Когда вы запустите программу, вывод будет:

  10
iOS
  

В приведенном выше примере целочисленное значение 10 присваивается константе age .Таким образом, оператор print (age) выводит 10 в консоли.

Аналогично, оператор let platform = "iOS" присваивает строковый литерал "iOS" константе platform . Таким образом, оператор print (platform) выводит iOS в консоль.

Пример 5: Оператор составного присваивания

  переменная x = 10
х - = 2
печать (x)  

Когда вы запустите программу, вывод будет:

  8  

Выражение x - = 2 использует составной оператор присваивания (- =) и является сокращением для x = x - 2 .Оператор является составным оператором присваивания, поскольку оператор одновременно выполняет вычитание и присваивание задачи.

Вы можете найти примеры побитовых операторов в этой статье Swift Побитовые операторы.


2. Арифметические операторы

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

Операторы быстрой арифметики
Оператор Значение
+ Сложение (также используется для конкатенации строк)
Оператор вычитания
* Оператор умножения
/ Оператор отдела
% Оператор остатка

Пример 6: Простые арифметические операции

  отпечаток (10 + 20)
печать (10-20)
печать (2 * 5)
print (5/2) // оператор деления
print (5% 2) // оператор остатка
print ("I love" + "Swift") // оператор также может использоваться для объединения строки
  

Когда вы запустите программу, вывод будет:

  30
-10
10
2
1
Я люблю Свифт
  

Пример 7: Арифметический оператор

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

  пусть x = 10/5
пусть y = 3% 2
печать (х)
печать (у)
  

Когда вы запустите программу, вывод будет:

  2
1
  

3.

Операторы сравнения

Эти операторы позволяют сравнивать два значения. Каждый из операторов сравнения возвращает значение типа Bool, чтобы указать, является ли утверждение истинным. Swift поддерживает следующие типы операторов сравнения:

Операторы быстрого сравнения
Оператор Значение Пример
== равно 5 == 3 оценивается как ложное
! = не равно 5! = 3 оценивается как истина
> больше 5> 3 оценивается как истинное
< менее 5 <3 оценивается как ложное
> = больше или равно 5> = 5 оценивается как истина
<= меньше или равно 4 <= 5 оценивается как истинное

Пример 8: Оператор сравнения

  let msg = "Привет"
print (msg == "Привет")
print (msg! = "Привет")
  

Когда вы запустите программу, вывод будет:

  верно
ложь  

Пример 9: Операторы сравнения больше и меньше

  отпечаток (10> 20)
печать (10 <20)
печать (5> = 5)
печать (5 <= 4)
  

Когда вы запустите программу, вывод будет:

  ложь
правда
правда
ложный
  

4.Логические операторы

Эти операторы используются с логическими (логическими) значениями и возвращают логическое значение. Он в основном используется для управления потоком программы с помощью if else, while или какого-либо другого управляющего оператора.

Логические операторы Swift
Оператор Значение Пример
|| Логическое ИЛИ; истина, если любое из логических выражений истинно ложь || истина оценивается как истина
&& Логическое И; истина, если все логические выражения верны false && true оценивается как false

Пример 10: Логический оператор

  печать (true && true)
печать (истина && ложь)
печать (ложь || истина)
  

Когда вы запустите программу, вывод будет:

  верно
ложный
правда  

В этой статье объясняются некоторые основные операторы Swift. Однако есть несколько более продвинутых операторов, таких как Range Operators, Nil-Coalescing Operator в Swift, о которых вы узнаете в следующих руководствах.

Далее вы узнаете о приоритете и ассоциативности операторов Swift. Проще говоря, это порядок выполнения этих операций в выражении.

бесплатный взлом с помощью Swift учебник

Операторы

- это те маленькие символы, которые вы выучили на самых первых уроках математики: + для сложения, - для вычитания, * для умножения, / для деления, = для присвоения значения и так далее.Все они существуют в Swift вместе с некоторыми дополнениями.

Давайте попробуем несколько основ - введите это в свою игровую площадку:

  var a = 10
а = а + 1
а = а - 1
а = а * а  

На панели результатов вы увидите 10, 11, 10 и 100 соответственно. А теперь попробуйте это:

  var b = 10
б + = 10
б - = 10  

+ = - оператор, означающий «добавить, затем назначить». В нашем случае это означает «взять текущее значение b , прибавить к нему 10, а затем вернуть результат в b ."Как вы можете себе представить, - = делает то же самое, но вычитает, а не добавляет. Таким образом, этот код покажет 10, 20, 10 на панели результатов.

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

  var a = 1,1
var b = 2.2
var c = a + b  

Когда дело доходит до струн, их соединяет + . Например:

  var name1 = "Тим МакГроу"
var name2 = "Ромео"
var both = name1 + "и" + name2  

Это напишет «Тим МакГроу и Ромео» в панели результатов.

Еще один распространенный оператор, который вы увидите, называется модулем и записывается с использованием символа процента: % . Это означает «разделить левое число поровну на правое и вернуть остаток». Итак, 9% 3 возвращает 0, потому что 3 делится на 9, тогда как 10% 3 возвращает 1, потому что 10 делится на 3 трижды, с остатком 1.

Примечание: Если вы купили Hacking with Swift и используете эксклюзивный путеводитель, сопровождающий курс, вам позже пригодится оператор модуля.

Операторы сравнения

Swift имеет набор операторов, выполняющих сравнение значений. Например:

  var a = 1,1
var b = 2.2
var c = a + b

с> 3
с> = 3
с> 4
с <4  

Это показывает, что больше (> ), больше или равно (> = ) и меньше ( <). В окне результатов вы увидите true, true, false, true - это логические значения, потому что ответ на каждое из этих утверждений может быть только истинным или ложным.

Если вы хотите проверить равенство, вы не можете использовать =, потому что он уже имеет значение: он используется для присвоения переменной значения. Итак, у Swift есть альтернатива в виде == , что означает «равно». Например:

  var name = "Тим МакГроу"
name == "Тим МакГроу"  

Это покажет "истина" на панели результатов. Теперь одна вещь, которая может вас уловить, - это то, что строки в Swift чувствительны к регистру, что означает, что «Tim McGraw», «TIM MCGRAW» и «TiM mCgRaW» считаются разными.Если вы используете == для сравнения двух строк, вам нужно убедиться, что они имеют одинаковый регистр букв.

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

  var stayOutTooLate = true
stayOutTooLate
! stayOutTooLate  

Это распечатает истину, истину, ложь - с последним значением там, потому что оно перевернуло предыдущее истину.

Вы также можете использовать ! с = , чтобы получить ! = или «не равно». Например:

  var name = "Тим МакГроу"
name == "Тим МакГроу"
name! = "Тим МакГроу"  

Спонсируйте взлом со Swift и войдите в крупнейшее в мире сообщество Swift!

Распространенных операторов Swift, о которых вы, возможно, не знаете

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

Тернарный условный оператор

Если у вас есть опыт программирования, то вы, вероятно, знаете о тернарном условном операторе . В Swift поведение этого оператора идентично C и Objective-C.

Этот оператор часто используется для замены простых операторов if-else . В приведенном ниже примере результат присваивания, использующего тернарный условный оператор, идентичен результату оператора if-else .Я уверен, что вы согласны с тем, что пример, в котором используется тернарный условный оператор, более элегантен и легче читается.

  var message = ""
пусть цена = 10.0

if price> 20.0 {
    message = "дорого"
} еще {
    message = "сделка"
}

сообщение = цена> 20.0? "дорого": "выгодно"
  

Без коалесценции

Оператор объединения nil с не существует в C и Objective-C. Однако идея проста. Взгляните на следующий пример.

  var a: Int?
var b = 5

пусть c = a ?? б
  

?? Оператор или nil coalescing проверяет значение на . Если a не имеет значения, по умолчанию используется значение, сохраненное в b . В приведенном выше примере c присвоено значение 5 .

Что мне нравится в ?? Оператор в Swift заключается в том, что он неявно разворачивает необязательный элемент и присваивает значение только в том случае, если параметр имеет значение. В приведенном выше примере показано, как это работает.

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

Swift определяет два оператора диапазона:

  • ... или привод замкнутого диапазона
  • .. < или привод полуоткрытого диапазона

Разница очевидна, как показано на примере ниже. Тело первого цикла for-in выполняется одиннадцать раз, тогда как тело второго цикла for-in выполняется только десять раз.

  для i в 0...10 {
    печать (я)
}

для i в 0 .. <10 {
    печать (я)
}
  

Оператор ... или закрытый диапазон включает конечное значение диапазона, тогда как оператор .. < или полуоткрытый исключает конечное значение диапазона.

Операторы диапазона очень полезны для перебора диапазона значений. Но почему Swift определяет два оператора диапазона? Это в первую очередь для удобства. Взгляните на следующий пример.

  пусть числа = [49, 27, 4, 32, 23, 431, 5]

для я в 0..  

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

Операторы равенства и идентичности

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

  Фонд импорта

пусть arr1 = NSArray (массив: [1, 2])
пусть arr2 = NSArray (массив: [1, 2])
пусть arr3 = arr2

print (arr1 == arr2) // верно
print (arr1 === arr2) // ложь
print (arr2 === arr3) // правда
  

Оператор == или равенство проверяет, равны ли два операнда. То, что равно означает для объекта, зависит от реализации класса или структуры. Для класса NSArray сравнивается содержимое массивов.В приведенном выше примере arr1 равно arr2 , потому что значения, хранящиеся в массивах, равны.

Оператор === или identity сравнивает идентичность объектов. Он проверяет, относятся ли операнды к одному и тому же объекту. Как видите, arr1 и arr2 не относятся к одному и тому же объекту, несмотря на то, что объекты равны. Однако идентичность arr2 и arr3 одинакова. Обе константы указывают на один и тот же объект.

Синтаксис подстрочного индекса

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

  let cities = ["Нью-Йорк", "Париж", "Берлин", "Лондон"]

печать (города [2])
  

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

Взгляните на следующий пример, в котором мы определяем структуры Item и ShoppingList . Чтобы добавить поддержку синтаксиса нижнего индекса в структуру ShoppingList , мы пишем определение нижнего индекса, используя ключевое слово subscript . Это позволяет нам запрашивать экземпляры ShoppingList , используя синтаксис индекса. Обратите внимание, что мы не используем ключевое слово func при создании определения индекса.

  struct Item {

    var price = 0,0
    имя переменной: Строка

    init (имя: String) {
        self. name = имя
    }

}

struct ShoppingList {

    var items = [Item] ()

    мутирующая функция addItem (_ item: Item) {
        items.append (элемент)
    }

    подстрочный индекс (индекс: Int) -> Элемент? {
        return (index  

Эта реализация позволяет нам использовать синтаксис индекса в экземплярах структуры ShoppingList .

  var shoppingList = ShoppingList ()

if let item = shoppingList [0] {
    печать (название предмета)
} еще {
    print («Ничего не найдено»)
}

shoppingList.addItem (Товар (имя: "Молоко"))

if let item = shoppingList [0] {
    печать (название предмета)
} еще {
    print («Ничего не найдено»)
}
  

Определение нижнего индекса в приведенном выше примере принимает значение типа Int . Если вы хотите, чтобы синтаксис нижнего индекса для класса ShoppingList работал также со значениями String , вам необходимо создать другое определение нижнего индекса.Таким образом, структура Dictionary , определенная в Swift Standard Library , добавляет поддержку синтаксиса подстрочного индекса.

Что дальше?

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

Вопросы? Оставьте их в комментариях ниже или напишите мне в Twitter.

Все об операторах в Swift | Лила Кришна | Swift India

→ Базовые операторы:

Оператор присваивания (a = b) инициализирует или обновляет значение « a » значением « b».

Swift поддерживает четыре стандартных арифметических оператора для всех типов чисел:

  • Сложение ( + )
  • Вычитание ( - )
  • Умножение ( * )
  • Деление (/)

Оператор остатка ( a% b ) определяет, сколько кратных b поместится внутри a , и возвращает оставшееся значение (известное как остаток ).

Пример:

9% 4 // равно 1

-9% 4 // равно -1

Знак числового значения можно переключать с помощью префикса - , известного как оператор унарного минуса . Оператор унарного минуса () добавляется непосредственно перед значением, с которым он работает, без пробелов.

Оператор унарного плюса ( + ) просто возвращает значение, с которым он работает, без каких-либо изменений:

  • Операторы составного назначения

Оператор объединения присваивания ( = ) с другими операторами.

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

  • Равно ( a == b )
  • Не равно ( a! = B )
  • Больше ( a> b )
  • Меньше ( a )
  • Больше или равно ( a> = b )
  • Меньше или равно ( a <= b )

Пример:

1 == 1 // верно, потому что 1 равно 1

2! = 1 // true, потому что 2 не равно 1

2> 1 // true, потому что 2 больше 1

1 <2 // true, потому что 1 меньше 2

1> = 1 / / true, потому что 1 больше или равно 1

2 <= 1 // false, потому что 2 не меньше или равно 1

  • Тернарный условный оператор

Тернарный условный оператор это специальный оператор из трех частей, который принимает форму вопроса ? ответ1: ответ2 .Это ярлык для оценки одного из двух выражений в зависимости от того, является ли вопрос истинным или ложным. Если вопрос верен, он оценивает ответ1 и возвращает его значение; в противном случае он оценивает answer2 и возвращает его значение.

Пример: hasEnoughMoney? makePayment (): discardPayment ()

Оператор nil-coalescing ( a ?? b ) разворачивает необязательный a , если он содержит значение, или возвращает значение по умолчанию b , если a равно ноль .Выражение a всегда имеет необязательный тип. Выражение b должно соответствовать типу, который хранится внутри a .

Пример:

var myLuckyNumber: Int?

var aNumber = myLuckyNumber ?? 007

в приведенном выше примере он оценивает первую переменную « myLuckyNumber », если она содержит значение, она разворачивает его и возвращает. В случае, если он не имеет значения, он возвращает «007» в качестве своего значения. Здесь должны совпадать оба типа.Вы не можете использовать любой другой тип, кроме Int , потому что « myLuckyNumber » имеет тип Int .

Пользовательские операторы в Swift | Swift от Sundell

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

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

Essential Developer: Присоединяйтесь к бесплатному онлайн-ускоренному курсу для разработчиков iOS, которые хотят стать старшими разработчиками с черным поясом, то есть: достичь экспертного уровня практических навыков и стать частью самых высокооплачиваемых разработчиков в мире.

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

  struct Resources {
    var gold: Int
    вар древесины: Int
}  

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

  struct Player {
    var resources: ресурсы
}  

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

  func trainUnit (ofKind kind: Unit.Kind) {
    let unit = Unit (kind: kind)
    board.add (блок)

    currentPlayer.resources.gold - = kind.cost.gold
    currentPlayer.resources.wood - = kind.cost.wood
}  

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

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

Давайте попробуем использовать оператор с перегрузкой , чтобы решить указанную выше проблему. При работе с операторами на большинстве языков (включая Swift) у вас есть два варианта. Либо вы перегрузите существующего оператора, либо создадите новый.Перегрузка работает так же, как перегрузка метода , в которой вы создаете новую версию оператора с новым вводом или выводом.

В этом случае мы определим перегрузку оператора - = , который работает с двумя значениями Resources , например:

  extension Resources {
    static func - = (lhs: inout Resources, rhs: Resources) {
        lhs.gold - = rhs.gold
        lhs.wood - = rhs.wood
    }
}  

Как и в случае соответствия Equatable , перегрузки операторов в Swift - это просто обычные статические функции, которые могут быть объявлены для типа.В случае - = левая часть оператора - это параметр inout , который является значением, которое мы изменяем.

Теперь, когда у нас есть перегрузка оператора, мы можем просто вызвать - = непосредственно для ресурсов текущего игрока, как и для любого примитивного числового значения:

  currentPlayer.resources - = kind.cost  

Not только это хорошо читается, это также помогает нам устранить проблему дублирования кода.Поскольку мы всегда хотим, чтобы вся внешняя логика изменяла экземпляры Resources в целом, мы можем пойти дальше и сделать свойства gold и wood только для чтения для всех других типов:

  struct Resources {
    частный (набор) var gold: Int
    private (set) var wood: Int

    init (золото: Int, дерево: Int) {
        self.gold = золото
        self.wood = дерево
    }
}  

Вышеупомянутое работает благодаря изменению в Swift 4, которое предоставило расширениям, определенным в том же файле частных привилегий.Таким образом, наша перегрузка оператора - = (и любые другие операторы или API, которые мы определяем для Resources ) может изменять свойства без необходимости их общедоступного изменения. Довольно мило!

Другим способом решения проблемы Resouces , описанной выше, было бы использование функции изменения вместо перегрузки оператора. Мы могли бы добавить функцию, которая уменьшает свойства значения Resources другим экземпляром, например:

  extension Resources {
    мутирующая функция уменьшения (по ресурсам: Ресурсы) {
        золото - = ресурсы. золото
        древесина - = resources.wood
    }
}  

Оба решения имеют свои достоинства, и вы можете утверждать, что подход с использованием функции мутации является более явным. Однако вам также не нужно, чтобы стандартный API вычитания для чисел был чем-то вроде 5.reduce (by: 3) , так что, возможно, это тот случай, когда перегрузка оператора имеет смысл.

Давайте посмотрим на другой сценарий, в котором использование перегрузки оператора может быть довольно приятным. Несмотря на то, что у нас есть Auto Layout и его мощный привязки макета API, иногда мы оказываемся в ситуациях, когда нам нужно выполнить расчеты макета вручную.

В подобных ситуациях очень часто приходится выполнять вычисления с двумерными значениями - например, CGPoint , CGSize и CGVector . Например, нам может потребоваться вычислить исходную точку метки, используя размер представления изображения и некоторые дополнительные поля, например:

  label.frame.origin = CGPoint (
    x: imageView.bounds.width + 10,
    y: imageView.bounds.height + 20
)  

Вместо того, чтобы постоянно увеличивать точки и размеры для использования их базовых компонентов, было бы неплохо, если бы мы могли просто сложить их (как мы это сделали с нашей структурой Resources )? 🤔

Чтобы сделать это, мы могли бы начать с перегрузки оператора + , чтобы он принял два экземпляра CGSize в качестве входных данных и вывести значение CGPoint :

  extension CGSize {
    static func + (lhs: CGSize, rhs: CGSize) -> CGPoint {
        вернуть CGPoint (
            x: lhs.ширина + правая ширина,
            y: lhs.height + rhs.height
        )
    }
}  

Теперь мы можем записать наш расчет макета следующим образом:

  label.frame.origin = imageView.bounds.size + CGSize (width: 10, height: 20)  

Это красиво круто, но кажется немного странным создавать CGSize для наших полей. Один из способов сделать это немного лучше - определить другую перегрузку + , которая принимает размер и кортеж, содержащий два значения CGFloat , например:

  extension CGSize {
    static func + (lhs: CGSize, rhs: (x: CGFloat, y: CGFloat)) -> CGPoint {
        вернуть CGPoint (
            x: lhs.ширина + rhs.x,
            y: lhs.height + rhs.y
        )
    }
}  

Что позволяет нам записать наш расчет макета любым из этих двух способов:

 
label.frame.origin = imageView.bounds.size + (x: 10, y: 20)


label.frame.origin = imageView.bounds.size + (10, 20)  

Это очень компактно и красиво! 👍 Но теперь мы подходим к сути проблемы, которая вызывает так много споров об операторах, - сбалансированности многословности и удобочитаемости. Поскольку мы по-прежнему имеем дело с числами, я думаю, что большинство людей найдут вышеизложенное довольно легко для чтения и понимания, но оно становится более сложным по мере того, как мы переходим к более индивидуальному использованию, особенно когда мы начинаем вводить новые операторы.

Чтобы узнать о дополнительных перегрузках операторов для типов Core Graphics, ознакомьтесь с CGOperators

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

Давайте посмотрим на другой пример. Механизм обработки ошибок Swift do, try, catch очень хорош при работе с ошибочными синхронными операциями. Это позволяет нам легко и безопасно выйти из функции при возникновении ошибки, например, при загрузке моделей, сохраненных на диске:

  class NoteManager {
    func loadNote (fromFileNamed fileName: String) выбрасывает -> Note {
        let file = попробуйте fileLoader.loadFile (имя: имя_файла)
        let data = попробуйте file.read ()
        let note = попробуйте Примечание (данные: данные)
        обратная записка
    }
}  

Единственным серьезным недостатком выполнения чего-то подобного вышеизложенному является то, что мы напрямую бросаем любые базовые ошибки вызывающему объекту нашей функции. Как я писал в своем самом первом сообщении в блоге - «Предоставление унифицированного API ошибок Swift» - обычно хорошей идеей является уменьшить количество ошибок, которые может выдать API, иначе выполнение значимой обработки ошибок и тестирования становится действительно трудным.

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

  extension NoteManager {
    enum LoadingError: Error {
        case invalidFile (Ошибка)
        case invalidData (Ошибка)
        case decodingFailed (Ошибка)
    }
}  

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

  class NoteManager {
    func loadNote (fromFileNamed fileName: String) выбрасывает -> Note {
        делать {
            let file = попробуйте fileLoader.loadFile (с именем: fileName)

            делать {
                let data = попробуйте file.read ()

                делать {
                    вернуться попробуйте Примечание (данные: данные)
                } ловить {
                    выбросить LoadingError.decodingFailed (ошибка)
                }
            } ловить {
                бросить LoadingError.invalidData (ошибка)
            }
        } ловить {
            выбросить LoadingError.invalidFile (ошибка)
        }
    }
}  

Я не думаю, что кто-то захочет читать код, подобный приведенному выше 😅. Один из вариантов - ввести функцию , выполняющую (как я сделал в вышеупомянутом сообщении), которую мы можем использовать для преобразования одной ошибки в другую:

  class NoteManager {
    func loadNote (fromFileNamed fileName: String) выбрасывает -> Note {
        let file = попробуйте выполнить (fileLoader. loadFile (с именем: fileName),
                               orThrow: LoadingError.invalidFile)

        let data = попробуйте выполнить (file.read (),
                               orThrow: LoadingError.invalidData)

        let note = попробуйте выполнить (Примечание (данные: данные),
                               orThrow: LoadingError.decodingFailed)

        обратная записка
    }
}  

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

Начнем с определения нашего нового оператора. В этом случае мы выберем ~>; в качестве символа (мотивируя это тем, что это альтернативный тип возврата , поэтому мы ищем что-то похожее на ->; ). Поскольку это оператор, который работает с двух сторон, мы определяем его как инфиксный , например:

  инфиксный оператор ~>  

Что делает операторы настолько мощными, так это то, что они могут автоматически захватывать контекст с обеих сторон их.Объедините это с функцией Swift @autoclosure , и мы сможем создать что-нибудь довольно крутое.

Реализуем ~>; как оператор, который принимает бросающее выражение и преобразование ошибки и либо генерирует, либо возвращает тот же тип, что и исходное выражение:

  func ~>  (выражение: @autoclosure () throws -> T,
           errorTransform: (Ошибка) -> Ошибка) выдает -> T {
    делать {
        вернуть выражение попытки ()
    } ловить {
        выбросить errorTransform (ошибка)
    }
}  

Итак, что нам позволяет сделать вышеперечисленное? Так как случаи перечисления со связанными значениями также являются статическими функциями в Swift, мы можем просто добавить ~>; между нашим выражением бросания и случаем ошибки, в который мы хотим преобразовать любую базовую ошибку, например:

  class NoteManager {
    func loadNote (fromFileNamed fileName: String) выбрасывает -> Note {
        let file = попробуйте fileLoader. loadFile (с именем: fileName) ~> LoadingError.invalidFile
        let data = try file.read () ~> LoadingError.invalidData
        let note = try Примечание (данные: данные) ~> LoadingError.decodingFailed
        обратная записка
    }
}  

Это круто! 🎉 Используя оператор, мы удалили много «мусора» и синтаксиса из нашей логики, сделав наш код более сфокусированным. Однако недостатком является то, что мы ввели новый вид синтаксиса для обработки ошибок, который, вероятно, будет совершенно незнаком каким-либо новым разработчикам, которые могут присоединиться к нашему проекту в будущем.

Essential Developer: Присоединяйтесь к бесплатному онлайн-ускоренному курсу для разработчиков iOS, которые хотят стать старшими разработчиками с черным поясом, то есть: достичь экспертного уровня практических навыков и стать частью самых высокооплачиваемых разработчиков в мире.

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

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

Как вы думаете? Дайте мне знать - вместе с любыми вопросами, комментариями или отзывами, которые могут у вас возникнуть - в Twitter @johnsundell. Чтобы узнать больше о Swift, перейдите на страницу категорий или посмотрите подкаст Swift by Sundell.

Спасибо за чтение! 🚀

Пользовательские операторы в Swift с практическими примерами кода

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

При разработке кода на Swift мы все довольно часто используем операторы по умолчанию. Сложение двух чисел с помощью знака + - это пример использования основных операторов, доступных в Swift. Давайте углубимся и посмотрим, как можно улучшить свой код с помощью настраиваемых операторов.

Примеры основных операторов, доступных в Swift

Чтобы полностью понять, что такое операторы, мы можем рассмотреть несколько примеров операторов, которые доступны в Swift по умолчанию. Некоторые могут быть для вас более очевидными, чем другие!

Например, очень часто используется оператор присваивания (очевидно), но он также является оператором!

  /// Пример оператора присваивания `=`.
let name = "Антуан"
пусть возраст = 29  

Существует несколько так называемых унарных операторов , таких как унарный префиксный оператор ! Value и унарный постфиксный оператор value! , также известный как оператор принудительного разворачивания

  /// Пример оператора унарного постфикса `!`.let forceUnwrappedURL: URL = URL (строка: "www.avanderlee.com")!

/// Пример оператора с унарным префиксом `!`.
пусть URLHasValue =! forceUnwrappedURL.absoluteString.isEmpty  

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

  /// Пример инфиксного оператора `+`.
пусть totalSum = 10 + 4  

Swift также поставляется с тернарным оператором , который работает по трем целям.Тернарный условный оператор позволяет нам писать операторы if в одной строке:

  /// Пример тернарного оператора `?:`, Тернарный условный оператор.
пусть title = page.hasTitle? page.title: "Без названия"  

Это всего лишь несколько примеров всех доступных операторов в Swift. Вы можете узнать больше об основных операторах в Swift Language Guide.

Создание собственного оператора

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

Создание настраиваемого оператора составного присваивания

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

Возьмем следующий пример, в котором у нас есть команда, полная членов:

  struct Team {
    let title: String
    private (set) var members: [Член]

    mutating func add (_ member: Member) {
        члены.добавить (член)
    }
}

struct Member {
    пусть имя: Строка
}  

Этот код позволяет нам написать следующий код, используя метод add (_ :) :

  var team = Команда (название: «Разработчики», участники: [Член (имя: «Антуан»)])

let newMember = Член (имя: "Борис")
team.add (newMember)  

Мы можем заменить этот код на оператора, который позволяет нам добавлять участников напрямую в команду, используя оператор + = :

  extension Team {
    static func + = (lhs: inout Team, rhs: Member) {
        lhs. добавить (rhs)
    }
}  

Давайте рассмотрим этот код шаг за шагом:

  • Сначала мы делаем расширение для нашей структуры Team
  • Оператор определяется как статический метод, в котором имя метода определяет оператор
  • Поскольку мы работаем со структурами, нам нужно использовать из , который добавляет требование наличия изменяемого экземпляра Team
  • Наконец, мы передаем нового участника, которого мы можем добавить в команду с помощью метода add (_ :)

Мы можем использовать этот оператор как следует:

  let newMember = Член (имя: "Борис")
команда + = newMember  

Операторы префикса и постфикса

Prefix и Postfix Операторы могут реже использоваться в качестве настраиваемых операторов.Когда мы думаем о примерах использования, это немного другое мышление. Тем не менее, вы можете сделать с ними довольно много приятных вещей.

В этом примере мы собираемся определить префикс , оператор . Однако таким же образом можно определить постфиксные операторы .

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

  пусть currencyFormatter = NumberFormatter ()
currencyFormatter.numberStyle = .currency
currencyFormatter.locale = Locale.current

пусть priceString = currencyFormatter.string (от: 9999,99)!

// Отображает 9 999,99 долларов США в текущем языковом стандарте, например, долларах США.
печать (priceString)  

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

  prefix func ~ (значение: NSNumber) -> String {
    let currencyFormatter = NumberFormatter ()
    currencyFormatter.numberStyle = .currency
    currencyFormatter.locale = Locale.current

    вернуть currencyFormatter.string (from: value)!
}  

При чтении этого определенного оператора префикса следует учитывать несколько моментов:

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

Этот пользовательский оператор можно использовать следующим образом:

  пусть decimalInputPrice: String = ~ 843.32
print (decimalInputPrice) // Выводит: 843,32 доллара

пусть intInputPrice: String = ~ 300
print (intInputPrice) // Выводит: $ 300,00  

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

Пользовательский оператор Infix

Операторы

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

Пример инфиксного оператора может выглядеть следующим образом:

  инфиксный оператор + -: AdditionPrecedence
extension Set {
    static func + - (lhs: Set, rhs: Set) -> Set {
        вернуть lhs. союз (правый)
    }
}  

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

  let firstNumbers: установите  = [1, 4, 5]
let secondNumbers: установите  = [1, 4, 6]
let uniqueNumbers = firstNumbers + - secondNumbers
print (uniqueNumbers) // Выводит: [1, 4, 5, 6]  

Расчет с помощью Emojis в Swift

Никогда не думал, что напишу о вычислении эмодзи в Swift, но это оказалось популярной первоапрельской шуткой 2020 года.

Многие думали, что я использовал Photoshop для создания результата, но факт в том, что на самом деле все это работало по-настоящему!

Вы можете узнать это по номерам строк слева и по зеленому знаку оператора + на используемом изображении:

Пользовательские операторы в Swift для расчета с помощью эмодзи

Теперь, когда вы знаете, как создавать свои собственные пользовательские операторы, неплохо было бы попробовать создать это для себя. Однако вы также можете просто взглянуть на код следующим образом:

  extension String {
    static func + (lhs: String, rhs: String) -> String {
        switch (lhs, rhs) {
        case ("?", "❄️"):
            возвращаться "?"
        case («?», «❄️»):
            возвращаться "?"
        кейс ("?", "?"):
            возвращаться "?"
        кейс ("?", "?"):
            возвращаться "?"
        кейс ("?", "?"):
            возвращаться "?"
        кейс ("?", "?"):
            возвращаться "?"
        кейс ("?", "?"):
            возвращаться "??"
        кейс ("?", "?"):
            возвращаться "?"
        кейс ("?", "?"):
            возвращаться "?"
        дефолт:
            print ("\ (lhs) и \ (rhs) не совпадают")
            вернуть "⁉️"
        }
    }
}  

Как видите, это просто пользовательский оператор инфикса для строк, который позволяет «вычислять» с разными смайликами.Теперь вы можете попробовать это на себе и начать добавлять свои собственные комбинации, из которых я, очевидно, хотел бы услышать от вас, какую комбинацию вы создали!

Игровая площадка нестандартных операторов

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

Заключение

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

Вам не хватает всего этого? Как насчет определения ваших собственных индексов в Swift .

Если вы хотите еще больше улучшить свои знания Swift, загляните на страницу категории Swift. Не стесняйтесь связаться со мной или написать мне в Твиттере, если у вас есть какие-либо дополнительные советы или отзывы.

Спасибо!

Как создавать собственные операторы и выполнять перегрузку операторов в Swift


Содержание

Что такое оператор

Оператор - это специальный символ, который вы используете с одним или несколькими значениями для получения определенного результата. Например, оператор сложения (+) складывает два числа и дает сумму между этими двумя, как в let i = 1 + 2 .

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

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

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

Мы можем разделить операторов на три группы.
Унарные операторы
Бинарные операторы
Тернарные операторы

Унарные операторы

Унарные операторы работают с одной целью, например -1,! BooleanValue.Унарный может появиться в двух местах.

  • Операторы унарного префикса , которые появляются непосредственно перед своими целевыми значениями, такими как отрицательное значение (–2 ) и логический оператор «не» (! BooleanValue ).
  • Унарные операторы постфикса , которые появляются сразу после своей цели, например, принудительное развертывание ( optionalValue! ).

Мы, , можем перегрузить и создать собственный префикс и постфиксный оператор.

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

Бинарные операторы работают с двумя целями (например, 2 + 3). Он может появляться только в между их двумя целями, инфиксным оператором .

Мы, , можем перегрузить и создать собственный инфиксный оператор.

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

Тернарные операторы работают с тремя целями, такими как тернарный условный оператор (a? B: c).

Мы, , не можем перегрузить или создать такой оператор.

Ограничение

Не каждый оператор может быть перегружен.Я знаю четыре ограничения:

  1. Вы не можете перегрузить и создать собственный тернарный оператор.
  2. Вы не можете перегрузить оператор присваивания по умолчанию ( = ). Вы можете перегрузить другие бинарные операторы, включая составные операторы присваивания, такие как a + = 2.
  3. Поддерживается только часть символов ASCII. Вы можете посмотреть полный список здесь.
  4. Некоторые символы и комбинации зарезервированы для некоторых операторов. Вы можете посмотреть полный список здесь.

Поскольку мы не можем перегрузить или создать тернарные операторы, у нас осталось три типа операторов, с которыми можно поиграть:
Префикс
Постфикс
Infix

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

Перегрузка существующих операторов

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

Infix

Начнем с перегрузки инфиксных операторов.

Перегрузка нового оператора в строках

Swift поддерживает четыре стандартных арифметических оператора для всех типов чисел:

  • Дополнение (+)
  • Вычитание (-)
  • Умножение (*)
  • Дивизия (/)

Строка Swift не поддерживает оператор *, но мы перегрузим оператор * для работы с ним. Мы перегрузим оператор *, чтобы он принимал в качестве аргументов строку и целое число, и создавал новую строку, представляющую данную строку, повторенную указанное количество раз.Результат будет выглядеть так:

  let str = "Ho!" 
str * 3

Как я упоминал ранее, вы можете рассматривать операторы как функцию со специальным именем. Чтобы объявить операторы перегрузки, мы бы сделали именно это.

Объявить как глобальную функцию
Вы можете объявить ее как глобальную функцию, подобную этой.

  func * (слева: String, справа: Int) -> String {
return String (повторение: слева, количество: справа)
}

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

  extension String {
static func * (left: String, right: Int) -> String {
return String (Repeating: left, count: right)
}
}

<1> Мы объявляем инфиксный оператор, который работает с двумя операндами, строкой и целым числом, и возвращает новую строку.
<2> Мы создаем новую строку, представляющую данную строку, повторяющуюся указанное количество раз.

И снова результат:

  let str = "Ho!" 
str * 3
Перегрузить существующие операторы другими аргументами.

Swift string уже перегружает операторы +, которые объединяют две строки вместе.

  общедоступная статическая функция + (lhs: String, rhs: String) -> String  

Результат:

  «Привет» + «Свифт!» 

Мы перегрузим оператор + другим аргументом.Наша новая перегрузка работает со строками и целыми числами и производит строку с последним повторяющимся символом, равным вторым операндам.

  extension String {
static func + (left: String, right: Int) -> String {
guard let lastCharacter = left.last else {
return left
}
return left + String (lastCharacter) * right
}
}

<1> Попытайтесь получить последний символ.
<2> Объединить строку с повторяющимся последним символом.

Результат:

  «Здравствуйте» + 5 

Префикс

Чтобы перегрузить префиксный оператор, нам нужно добавить ключевое слово prefix перед func .

В следующем примере я перегружаю унарный оператор для строки, который меняет местами символы в данной строке.

  static prefix func - (str: String) -> String {
return String (str.reversed ())
}

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

И вот результат:

  - «Здравствуйте» 

Postfix

Чтобы перегрузить постфиксный оператор, нам нужно добавить ключевое слово postfix перед func .

В следующем примере я перегружаю унарный оператор ... для строки, который добавит строку «...» в конец данной строки.

  static postfix func ... (str: String) -> String {
return str + "..."
}

<1> Мы добавляем ключевое слово postfix , чтобы сообщить компилятору, что оно предназначено для использования в качестве постфиксного оператора.. «Привет, Свифт»

Разница между существующим оператором перегрузки и пользовательским

Как видите, единственная разница между существующим оператором перегрузки и настраиваемым - , объявляющая новый оператор . Если вы этого не сделаете, компилятор выдаст вам эту ошибку.

  Реализация оператора без соответствующего объявления оператора.  

Реализация оператора без соответствующей ошибки объявления оператора

Заключение

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

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

  • Быстрый язык программирования
  • Документация Apple

Подробнее о

Быстрый,

Оператор,

или посмотреть все доступные темы

Не стесняйтесь подписываться на меня в Твиттере и задавать свои вопросы, связанные с этим постом. Спасибо, что прочитали, и увидимся в следующий раз.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *