Быстрый. Class && Struct (Классы И Структуры), Часть 2

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

Ссылка на первую часть - Тыц



Подводим итоги последней публикации

Мы знаем этот класс:
  • имеет свойства и методы
  • может описать объект (экземпляр)
  • может описывать тип (глобальные возможности)
  • может использоваться как тип и как экземпляр одновременно, при этом свойства и методы типа не пересекаются со свойствами и методами экземпляра
  • может использовать свой собственный экземпляр в свойстве типа, чтобы обеспечить однократную инициализацию
  • может быть родительским (суперкласс) и иметь родительского (наследовать реализацию суперкласса)
  • может переопределить наследие суперкласса
  • может запретить переопределение и ограничить доступ к свойствам и методам
  • может наследовать несколько классов в цепочке (всегда есть один Суперкласс)
  • это ссылочный тип значения
Вроде ничего из описанного ранее я не упустил, продолжим, но сегодня копнем немного глубже.

Начнем с того, что помимо возможности инициализировать экземпляр в свойство типа

  
  
  
  
  
   

class ExampleClass { static var shared: ExampleClass = ExampleClass() var name: String = "name" }

у нас есть возможность инициализировать экземпляр экземпляра

class ExampleClass { var instance: ExampleClass? var name: String = "name" }

примечание что я использую необязательное значение при построении класса, реализованное в целях безопасности, поскольку неудачная инициализация такой конструкции без использования сетей безопасности приведет к переполнению памяти (класс будет бесконечно инициализироваться внутри себя)

Быстрый.
</p><p>
 Class && Struct (классы и структуры), часть 2

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

Из предыдущей публикации вы уже знаете, что класс с определёнными свойствами имеет инициализатор по умолчанию (инициализатор по умолчанию).

Он существует в связи с отсутствием аналогичного инициализатора, реализованного разработчиком, во избежание своеобразного конфликта интересов.



Быстрый.
</p><p>
 Class && Struct (классы и структуры), часть 2

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



Быстрый.
</p><p>
 Class && Struct (классы и структуры), часть 2

пример использования удобных инициализаторов Примечание! На изображении выше вы можете увидеть имена "Единица" И "Несколько" , они относятся к переданным параметрам, а не к инициализаторам, т.е.

экземпляру с именем "Единица" получает Int, и с именем «Несколько» [Инт].

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

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

  • Вспомогательный инициализатор должен вызывать другой инициализатор.

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



Быстрый.
</p><p>
 Class && Struct (классы и структуры), часть 2

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

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

Фактически мы получаем приведенные выше правила.

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

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

.



Быстрый.
</p><p>
 Class && Struct (классы и структуры), часть 2

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



Быстрый.
</p><p>
 Class && Struct (классы и структуры), часть 2

усложнение логики инициализатора Внимательный читатель мог заметить замену цикла суммирования на сокращение.

Пояснения будут в конце публикации, поскольку не имеют прямого отношения к теме.

Небольшое отступление, потому что.

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



Быстрый.
</p><p>
 Class && Struct (классы и структуры), часть 2

замена если с переключателем но давайте продолжим с инициализаторами.

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

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

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



Быстрый.
</p><p>
 Class && Struct (классы и структуры), часть 2

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

ноль в любых ситуациях.

Есть еще один нюанс и правило, касающееся инициализаторов классов.

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



Быстрый.
</p><p>
 Class && Struct (классы и структуры), часть 2

вызов инициализатора суперкласса

Быстрый.
</p><p>
 Class && Struct (классы и структуры), часть 2

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

Давайте теперь поговорим о деинициализаторах.

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

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



class Product { var collection: Collection! var category: Category! } class Collection { var category : Category? let product : Product } class Category { var collection : Collection? let product : Product }

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

Собственно, давайте добавим инициализаторы в наши классы.



.

///Product init(){ self.collection = Collection(nil, self) self.category = Category(self.collection, self) self.collection.category = self.category } .

///Collection init(_ cat: Category?, _ prodo: Product){ self.category = cat self.product = prodo } .

///Category init(_ col: Collection, _ prodo: Product){ self.collection = col self.product = prodo } .



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

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

Объект указан, его нет в переменной/константе, т.е.

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

.

///Product func removeCategory() { collection.category = nil self.category = nil } .



Мы также добавим деинициализатор категорий.



.

///Category deinit{

Теги: #Разработка для iOS #Swift #network #class #init #struct #didset #get

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.