Данная публикация является второй частью ранее опубликованного материала и предназначена для ознакомления с ним.
Ссылка на первую часть - Тыц
Подводим итоги последней публикации
Мы знаем этот класс:- имеет свойства и методы
- может описать объект (экземпляр)
- может описывать тип (глобальные возможности)
- может использоваться как тип и как экземпляр одновременно, при этом свойства и методы типа не пересекаются со свойствами и методами экземпляра
- может использовать свой собственный экземпляр в свойстве типа, чтобы обеспечить однократную инициализацию
- может быть родительским (суперкласс) и иметь родительского (наследовать реализацию суперкласса)
- может переопределить наследие суперкласса
- может запретить переопределение и ограничить доступ к свойствам и методам
- может наследовать несколько классов в цепочке (всегда есть один Суперкласс)
- это ссылочный тип значения
Начнем с того, что помимо возможности инициализировать экземпляр в свойство типа
у нас есть возможность инициализировать экземпляр экземпляраclass ExampleClass { static var shared: ExampleClass = ExampleClass() var name: String = "name" }
class ExampleClass {
var instance: ExampleClass?
var name: String = "name"
}
примечание что я использую необязательное значение при построении класса, реализованное в целях безопасности, поскольку неудачная инициализация такой конструкции без использования сетей безопасности приведет к переполнению памяти (класс будет бесконечно инициализироваться внутри себя)
демонстрация использования экземпляра внутри экземпляра Конечно, мы рассмотрим преимущества совмещения использования экземпляра и типа на примере, но перед этим давайте немного пройдемся по инициализаторам и деинициализаторам.
Из предыдущей публикации вы уже знаете, что класс с определёнными свойствами имеет инициализатор по умолчанию (инициализатор по умолчанию).
Он существует в связи с отсутствием аналогичного инициализатора, реализованного разработчиком, во избежание своеобразного конфликта интересов.
пример переопределения инициализатора по умолчанию Кроме того, инициализаторов может быть много и они могут использовать друг друга (делегированная инициализация).
пример использования удобных инициализаторов Примечание! На изображении выше вы можете увидеть имена "Единица" И "Несколько" , они относятся к переданным параметрам, а не к инициализаторам, т.е.
экземпляру с именем "Единица" получает Int, и с именем «Несколько» [Инт].
На изображении выше есть два типа инициализаторов: "назначен" (обычный инициализатор, который гарантирует готовность всех свойств после завершения; инициализатор по умолчанию, обсуждавшийся ранее, является назначенным) и "комфортный" (удобство), удобный инициализатор (вспомогательный) называется удобным, потому что.
ему не обязательно определять все свойства, но следует помнить простые правила.
- Вспомогательный инициализатор должен вызывать другой инициализатор.
- Вспомогательный инициализатор должен вызывать назначенный инициализатор, но не обязательно напрямую.
пример косвенного вызова назначенного инициализатора из вспомогательного устройства Приведенный выше код работает таким образом, что первый вспомогательный метод вызывает второй, а второй — назначенный.
Другими словами, вспомогательный инициализатор должен вызывать назначенный инициализатор, но не обязательно делать это напрямую и для этих целей может вызывать другой вспомогательный инициализатор, который уже вызывает назначенный.
Фактически мы получаем приведенные выше правила.
Стоит отметить, что при проектировании класса не обязательно использовать вспомогательные инициализаторы; можно определить логику в заданных, все всегда зависит от сложности класса и поставленных задач.
Например, в рамках реализации приведенного выше класса логичнее отказаться от вспомогательных в пользу назначенных, поскольку нам не нужно использовать переменные (подойдут константы), а вспомогательные инициализаторы лишают нас этой возможности.
.
реализация без использования удобных инициализаторов Кроме того, Swift позволяет организовать более сложную логику в одном инициализаторе.
усложнение логики инициализатора Внимательный читатель мог заметить замену цикла суммирования на сокращение.
Пояснения будут в конце публикации, поскольку не имеют прямого отношения к теме.
Небольшое отступление, потому что.
Хочу обратить ваше внимание на выключатель В Быстрый потому что он мощнее, чем кажется на первый взгляд (не подводит как выключатель В С, работает с диапазонами и т. д.), а также с лихвой заменит громоздкий дизайн если еще, если.
замена если с переключателем но давайте продолжим с инициализаторами.
В дополнение к назначенным и вспомогательным инициализаторам вы можете использовать неудачные инициализаторы, которые могут возвращать ноль.
Например, нам нужен некий экземпляр, свойство которого должно делиться на 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
-
История О Том, Как Я Не Нашел Инженера
19 Oct, 24