Определение существования объекта с помощью Swift

Одна из самых сложных концепций для языка программирования (или любого другого языка на самом деле) заключается в том, что объект не существует. Swift использует термин nil для обозначения отсутствия объекта. На первый взгляд кажется, что это мало что значит, но если копнуть глубже, можно обнаружить множество подводных камней, с которыми разработчик потенциально может столкнуться, работая с языком, имеющим такое тщеславие. Что произойдет, если вы попытаетесь получить доступ к этому объекту опасным способом? Как узнать, что объект может быть нулевым? Как убедиться, что он не равен нулю при работе с ним?

Со Swift решение является необязательным. Вы можете обозначить объект как необязательный, добавив ? или ! к типу при его определении. Возьмем, к примеру, персонажа «Властелин колец» Голлума. В определенные моменты истории у него есть Кольцо, в других случаях - нет. Если бы мы создавали структуру или класс Голлума, мы могли бы использовать дополнительные опции для моделирования этого сценария.

В нашей структуре Gollum есть переменная с именем theRing, которая является необязательным объектом TheOneRing. Когда Голлум контролирует кольцо, это значение устанавливается. Когда он этого не делает, theRing становится nil.

Прежде чем мы с головой погрузимся в использование дополнительных опций, давайте подробнее рассмотрим, что они из себя представляют. Необязательный параметр - это не что иное, как перечисление с двумя регистрами: .some и .none. Когда ваш optional содержит объект, регистр .some имеет связанное значение, когда его нет, регистр .none указывает, что ваш optional is nil. Это означает, что вы можете обрабатывать необязательные значения так же, как и любое другое перечисление в Swift. В нашем theRing примере, приведенном выше, это будет выглядеть так:

Это просто оператор switch для объекта theRing. Если у него есть связанное значение, тогда оно попадет в регистр .some и будет напечатано theRing, если нет, то оно попадет в регистр .none и будет напечатано Nothing here.

Распаковка опций

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

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

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

Вот и все! Если параметр magician содержит значение, этот объект разворачивается и вызывается его функция doTrick(). Если вместо этого будет nil, то при вызове attemptTrick(with: Magician?) ничего не произойдет.

Другое использование оператора ? - необязательная цепочка. Допустим, у вас есть необязательный тип, в который вложен другой необязательный тип, и вы хотите получить доступ к атрибуту вложенного необязательного типа. Наш тип Magician имеет необязательный тип Prop, давайте теперь определим тип Prop с дополнительным атрибутом isAvailable, который будет имитировать, доступен ли prop или нет.

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

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

Хотя в этом нет особого смысла. Реквизит либо есть, либо недоступен, никогда не бывает времени, когда это может быть что-то еще. Давайте воспользуемся новой техникой, известной как if let, чтобы развернуть наши опции и очистить функцию. При использовании синтаксисаif let вы в основном говорите: «Если я могу позволить своему объекту быть тем, что я разворачиваю, сделайте код в фигурных скобках». Он следует той же логике, что и любой другой оператор if. Следует иметь в виду, что объект, который вы разворачиваете, доступен только в рамках оператора if, он не существует за пределами фигурных скобок.

Я прочитал это так: «Если я могу позволить опоре быть равной опоре фокусника, верни истину, иначе верни ложь». Эта функция теперь не только возвращает фактическое значение каждый раз, но и означает, что вы можете очистить тип Prop, удалив атрибут isAvailable.

Использование заявлений защиты

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

До сих пор мы использовали оператор ? исключительно в нашем коде, теперь давайте взглянем на его озорного двойника, оператора !. Использование ! для развертывания необязательного элемента называется принудительным развертыванием. По сути, это означает, что вы знаете, что ваш необязательный параметр имеет значение. На самом деле, вы настолько уверены, что оно имеет ценность, что готовы рискнуть привести к сбою приложения, если это не так. Это последствие использования !: если оно выполнено некачественно, ваше приложение перестает работать. Вы можете спросить себя: «Если последствия столь велики, зачем мне их использовать?». Что, если вы пишете фрагмент кода и хотите быть абсолютно уверены в том, что ваше приложение находится в определенном состоянии, прежде чем продолжить? Если он находится не в правильном состоянии, возможно, лучше будет выйти из строя, чем продолжать работу. Вот наш обновленный пример с принудительным развертыванием:

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

Замена на ноль

Последняя часть необязательности, о которой я хотел бы рассказать, - это оператор объединения с нулевым значением ??. Этот оператор позволяет вам заменить объект на nil. Представьте, что наш фокусник заболевает и его заменяет дублер. Это выглядит так:

Эта функция примет ваш первый выбор фокусника, но если этот маг вернет nil, он создаст новый экземпляр типа magician и вместо этого вернет его. У вас всегда будет фокусник на шоу!

Подведение итогов

Некоторые считают опциональные опции самой сложной для понимания частью языка. Они определенно сбили меня с толку, когда я только начал изучать Swift. Я пришел из среды Java, где дополнительных опций не существует. Вместо этого вы научились проверять null перед использованием значения. Альтернатива - крах. На мой взгляд, дополнительные возможности - одно из самых больших преимуществ Swift перед таким языком, как Java. Да, с ними связана кривая обучения, но хорошее понимание их использования существенно повлияет на то, как вы пишете приложения.