Не спорт, совместное использование типов значений в качестве ссылочных типов
Как всегда с более продвинутыми функциями Swift, необходимо подумать, подходит ли эта функция для ситуации, которую вы сейчас видите.
Типы значений копируются при копировании экземпляра, а это означает, что нам не нужно иметь дело со ссылками, что упрощает отладку нашего кода. Но что, если бы мы захотели поделиться типом значения — то есть иметь дело со ссылкой на него в конкретной ситуации, чтобы разделить типы значений в нескольких местах вашего приложения?
Добро пожаловать в бокс!
Сложность: Новичок | Легко| Нормальный | Сложно
Предпосылки:
- Уметь создавать Hello, World! iOS-приложение (гид ЗДЕСЬ)
- Знайте, когда использовать класс или структуру в конкретных ситуациях (руководство ЗДЕСЬ)
Терминология
Бокс: процесс преобразования типа значения в ссылочный тип
Класс: объект, который определяет общие свойства и методы, используя семантику передачи по ссылке.
Ссылка: указатель на переменную или объект
Ссылочный тип: тип, который означает, что экземпляры имеют единственную копию данных.
Struct: объект, определенный в Swift, с использованием семантики передачи по значению.
Значение: то, что будет храниться в переменной
Тип значения: тип, означающий, что каждый экземпляр имеет копию данных.
Простые структуры
Structs
являются value types
, что означает, что они обычно выбираются вместо классов (которые являются reference types
), поскольку их использование означает, что код, вероятно, будет легче поддерживать, а также легче отлаживать.
Value types
не используются в нескольких местах вашего приложения, а копируются. Следующая демонстрация объясняет, как можно скопировать struct
.
Использование структуры
Одним из возможных value type
является struct
, и мы можем хранить данные в свойствах этого data type
.
struct Person { var name: String var age: Int }
и мы можем объявить отдельного человека, что
let steve = Person(name: "Steve", age: 22)
теперь это, как упоминалось выше, value type
.
Поэтому мы можем создать копию struct
, а затем изменить этот struct
, не изменяя исходный экземпляр. Это выглядит примерно так:
var secondSteve = steve secondSteve.age = 33
Когда мы печатаем, два экземпляра (steve и secondSteve) действительно имеют разный возраст — 22 и 33 года соответственно.
print (steve) // Person(name: "Steve", age: 22) print (secondSteve) // Person(name: "Steve", age: 33)
Мини-вывод из этого состоит в том, что когда мы передаем value type
(контроллерам представления или где-либо еще), создается копия — и мы можем не захотеть, чтобы наша структура имела свойства value type
— временно и в ситуации, когда мы хотим поделиться Struct
в приложении для iOS.
Использование контейнера класса
Заключение Person в Class
будет означать, что вы можете поделиться Class
(называемым ниже PersonBoxed), и он будет рассматриваться как class
(и под этим, в частности, мы подразумеваем это будет рассматриваться как reference type
)
class PersonBoxed { var person: Person init(person: Person) { self.person = person } }
Создание экземпляра PersonBoxed может быть затем создано и создано с помощью Person Struct
:
let personBoxed = PersonBoxed(person: steve)
Итак, как и прежде, мы создаем второй экземпляр personBoxed и выбираем другой возраст для этого человека. Сложно получить доступ к человеку в поле, а затем к возрасту в этом поле, но синтаксис должен быть достаточно ясным:
var secondPersonBoxed = personBoxed secondPersonBoxed.person.age = 33
Поскольку мы используем семантику reference
, этот secondPersonBoxed фактически указывает на один и тот же экземпляр
print (personBoxed.person) // Person(name: "Steve", age: 33) print (secondPersonBoxed.person) // Person(name: "Steve", age: 33)
Так что действительно, наш Struct
теперь преподносится как Class
, чего можно было ожидать, когда мы завернули наш Struct
в Class
. С точки зрения справочной семантики, соблюдается именно этот набор правил.
Вывод
Бокс позволяет нам рассматривать value types
как reference types
. Разница может показаться довольно технической и неактуальной для многих программистов.
Однако, если вы хотите использовать семантику reference
, и вы можете захотеть сделать это для модели в вашем приложении (например, создание копии модели для каждого контроллера представления было бы катастрофой), представьте, что у вас есть простой переключатель это может включить семантику reference
.
Это точно. Мы включаем семантику reference
для тех value types
, которые мы выбираем; когда и где мы решим это сделать.
Фантастико.
Код
Это довольно коротко, так что вот вся копи-паста для этой статьи в виде GIST:
Расширьте свои знания
- Предложения Swift Evolution для данных предлагаются ЗДЕСЬ
Контакт в Твиттере:
Любые вопросы? Связаться со мной можно здесь