Convenient Initialization
Previous initializers were called specified initializers (required, no system will generate a default), and convenient initializers
Uses of convenient initializers
The specified initializer is not to be overlooked. The convenience initializer does work with the specified initializer in the data I have available at this time. In addition, the convenience initializer cannot be used in the structure.
class Person { var a:Int,b:Int init(a:Int,b:Int) { self.a = a self.b = b } convenience init(a:Int) { self.init(a:a,b:10) } }
For example, this initializer has two scenarios where a and B both have values and one only needs to be assigned. In this case, there are actually two choices, 1. Write multiple specified initializers, 2. Write one specified initializer and multiple convenient initializers
Generally speaking, the recommended writing is a specified initializer + multiple convenient initializers, so that the structure inside the inheritance is clearer (explained in the inheritance), and that the same initializer is called locally. Some uniform settings can also be written together
class Person { var a:Int,b:Int init(a:Int,b:Int) { self.a = a self.b = b } convenience init(a:Int) { self.init(a:a,b:10) } convenience init(b:Int) { self.init(a:10,b:b) } convenience init() { self.init(a:10,b:10) } }
For example, in this particularly complex case, if you need to set something to this class, the Write Instruction Initializer has to write all the settings in these four cases (since the Instruction Initializer can only adjust the Instruction Initializer of the parent class, not the same class).
Instruction Initializer and Convenient Initializer Use Within Inheritance
In inheritance, it is generally only a command initializer call, not a convenient initializer
So the general recommendation when inheriting is
The same class, multiple convenient initializers, one specified initializer, unless it is final class, it is not recommended to write more than one specified initializer, otherwise there will be dozens of initialization combinations, which directly make it dizzy, bad for module design, and difficult to maintain later. Like this mode, convenient initializers can only find initializers of this class. Instruction Initializer then looks for Instruction Initializer of the parent class so that inheritance is a line and can be varied locally
Inter-Initializer Call Rules
Convenient Initializer can only call Convenient Initializer and Instruction Initializer of this class
Instruction initializer can only call instruction initializer of parent class
Two-Segment Initialization
I always encounter when I just wrote code
self.c = c
super.init(a: a, b: b)
Writing this code in the wrong order can cause problems such as errors because of two initializations
Stage 1: Initialize all storage properties
1. Outer Call Initializer ------ is the Outer Call Initializer
2. Allocate storage but not initialize -------------- Initialization begins after outer layer call, first malloc, where only space is allocated but not actually initialized
3. Specify an initializer to ensure that all storage properties can be initialized --------- that is, specify an initializer to initialize all storage properties
4. Call the parent initializer, and keep going up to form the initializer chain ------------------- If the initializer of this class is not sufficient to initialize all the storage properties, call the initializer of the parent class as self.c = c must be written in super. Before init()
So the purpose of the first phase is to ensure that all storage properties can be initialized
class Person { var a:Int,b:Int init(a:Int,b:Int) { self.a = a self.b = b // end } convenience init(a:Int) { self.init(a:a,b:10) } convenience init(b:Int) { self.init(a:10,b:b) } convenience init() { self.init(a:10) self.b = 10 } } class Teacher: Person { var c:Int init(a: Int, b: Int, c: Int) { self.c = c super.init(a: a, b: b) } convenience init(a:Int) { self.init(a: a, b: 2,c: 5) } } Person(a:10)
Like this code, suppose initializing a Person goes through the convenient initializer int(a:Int), then initializes c to the instruction initializer, then invokes the instruction initializer of the parent class to initialize a, and then the first phase of initialization ends
Stage 2: Setting new storage property values
It feels like initialization is finished after the first stage, and everything else inside the initializer can be executed, so self. Functions cannot be written before the first phase of initialization, such as
class Teacher: Person { var c:Int init(a: Int, b: Int, c: Int) { self.ptr() self.c = c super.init(a: a, b: b) self.ptr() } convenience init(a:Int) { self.init(a: a, b: 2,c: 5) } func ptr() { print("sth") } }
self.ptr is written on self.c = c This line is preceded by an error because the first phase of initialization has not completed self. Functions are meaningless
Security check
1. The subclass storage object must be initialized before the parent class can be invoked, because the initializer of the parent class cannot initialize the subclass storage property, that is, self. Property initialization such as C = C must be written in super. Before init
2. Even if the subclass assigns values to the parent's storage properties, the parent's initializer must be invoked first
For example, this self.a = a is an error because the first stage initialization of the parent class has not been completed or even invoked
Convenient initializers also have to have the specified initializers initialized before they can be manipulated
In short, you cannot use self in an initializer until one phase of initialization is complete. Do everything except initialization, and local initialization must take precedence
Override Initializer
Parameter return value is the same, content is biased is overridden
class Person { var a:Int,b:Int init(a:Int,b:Int) { self.a = a self.b = b } } class Teacher: Person { var c:Int init(a: Int, b: Int, c: Int) { self.c = c super.init(a: a, b: b) } override init(a:Int,b:Int) { self.c = 10 super.init(a: a, b: b) } }
It seems that overriding an initializer is not very meaningful, because c still needs to be assigned a value, and it can become more complex to use in inheritance. It is worth noting that subclasses cannot override the convenient initializer of a parent class
In addition, if the subclass does not write an initializer, it automatically inherits all the instruction initializers of the parent class, and the individual feels that unless the subclass has no storage properties, it will write an initializer