Из документов
Проверка безопасности 1
Назначенный инициализатор должен гарантировать, что все свойства, представленные его классом, инициализируются, прежде чем он делегирует вплоть до инициализатора суперкласса.
Зачем нам нужна проверка безопасности, как это?
Чтобы ответить на этот вопрос, давайте перейдем к процессу инициализации в Swift.
Двухфазная инициализация
Инициализация класса в Swift является двухфазным процессом. На первом этапе каждому сохраненному свойству присваивается начальное значение классом, который его ввел. Как только начальное состояние для каждого сохраненного свойства определено, начинается второй этап, и каждому классу предоставляется возможность дополнительно настроить свои сохраненные свойства, прежде чем новый экземпляр будет считаться готовым к использованию.
Использование двухфазного процесса инициализации делает инициализацию безопасной, при этом обеспечивая полную гибкость каждому классу в иерархии классов. Двухфазная инициализация предотвращает доступ к значениям свойств до их инициализации и предотвращает неожиданное изменение значений свойств другим инициализатором.
Итак, чтобы убедиться, что двухэтапный процесс инициализации выполнен так, как определено выше, есть четыре проверки безопасности, одна из которых,
Проверка безопасности 1
Назначенный инициализатор должен гарантировать, что все свойства, представленные его классом, инициализируются, прежде чем он делегирует вплоть до инициализатора суперкласса.
Теперь, двухфазная инициализация никогда не говорит о порядке, но эта проверка безопасности, вводит super.init
в после инициализации всех свойств.
Проверка безопасности 1 может показаться неуместной, поскольку
двухфазная инициализация предотвращает доступ к значениям свойств до того, как они будут выполнены, без этой проверки безопасности 1.
Как в этом примере
class Shape {
var name: String
var sides : Int
init(sides:Int, named: String) {
self.sides = sides
self.name = named
}
}
class Triangle: Shape {
var hypotenuse: Int
init(hypotenuse:Int) {
super.init(sides: 3, named: "Triangle")
self.hypotenuse = hypotenuse
}
}
Triangle.init
инициализировал каждое свойство перед использованием. Так что проверка безопасности 1 кажется неактуальной,
Но тогда может быть другой сценарий, немного сложнее,
class Shape {
var name: String
var sides : Int
init(sides:Int, named: String) {
self.sides = sides
self.name = named
printShapeDescription()
}
func printShapeDescription() {
print("Shape Name :\(self.name)")
print("Sides :\(self.sides)")
}
}
class Triangle: Shape {
var hypotenuse: Int
init(hypotenuse:Int) {
self.hypotenuse = hypotenuse
super.init(sides: 3, named: "Triangle")
}
override func printShapeDescription() {
super.printShapeDescription()
print("Hypotenuse :\(self.hypotenuse)")
}
}
let triangle = Triangle(hypotenuse: 12)
Вывод :
Shape Name :Triangle
Sides :3
Hypotenuse :12
Здесь, если бы мы вызвали super.init
перед установкой hypotenuse
, то super.init
вызов вызвал бы printShapeDescription()
и, так как это было переопределено, он сначала вернулся бы к реализации класса Triangle printShapeDescription()
. Класс printShapeDescription()
Triangle обращается к hypotenuse
необязательному свойству, которое еще не было инициализировано. И это запрещено двухфазная инициализация предотвращает доступ к значениям свойств до их инициализации.
Поэтому убедитесь, что двухфазная инициализация выполняется в соответствии с определением, должен быть определенный порядок вызовов super.init
, то есть после инициализации всех свойств, введенных self
классом, нам нужна проверка безопасности 1