The Swift constructor explores when to use the constructor? For classes (Class)
In other languages, for example, Java has no strict requirements for the initialization of attributes. Even the model layer has only the corresponding property of the Get,set accessor. In Swift, whether it is a struct (Structure) or a class, if there is a storage attribute (stored property), it must be assigned an initial value in the appropriate place, that is, initialization. They cannot be made in an indeterminate state, that is, without initialization. With regard to initialization, Swift provides two ways. One is initialization when the attribute is defined, that is, assigning the default value. The second type is initialized in the constructor.
Here's a summary: the storage properties must be initialized, the initialization method can only be selected in the above two ways, and contains at least one of them.
For the first, there are two other ways to initialize in Swift. The first is to give a definite value. For examplevar name = "Bob", Swift's data type inference mechanism automatically infers that nameit is a string type variable with an initial value ofBob. The second is the optional type initialization, which is usually used when this property may or may not exist when the program is running. For example, var avatar: UIImage? A person may not have a picture. SupposeavatarIt isPersona stored property of a class, the program runs the procedure, if thePersonclass creates an instancelet myPerson = Person (), if the assignment is not givenmyPerson.avatar, thenmyPersontheavatarproperty is automatically initializednil. IfmyPerson.avatar = UIImage (named: "prettyGirl") so, then the Avatar property is initializedUIImage (named: "prettyGirl").
For the second type of initialization, more specifically, it is necessary to implement the first type of initialization if it is not implemented. That is, if you define a property thatvar avatar: UIImagedoes not give an explicit initial value and does not make it a optional type, you must implement initialization in the constructor. This is when to use the focus of the constructor.
However, Swift's constructor has two kinds, one is the designated constructor and the other is the convenience constructor. All designated constructors must initialize storage properties that do not meet the first case. Note that this is what all the designated constructors in the class have to do. Please see the following text designated constructor
For structural bodies (Structure)
The struct and class constructors in Swift are similar in fact. In addition to structs that do not have destructors (Deinitializer), they cannot be inherited (inherit) and structs are generally consistent outside of memberwise constructors. So you sometimes see a structstruct Pointwith two storage properties, var x: Doublevar y: Doublewithout any constructors, but they do not conform to the first initialization method discussed in the class (that is, assigning default values). So do they violate the rules of grammar? In fact, if the struct does not have a custom constructor, Swift implicitly creates ainit (x: y:) constructor whose content is equivalentself.x = x, self.y = y. If you manually add an empty content constructor to the struct, theinit () { } compiler will reportReturn from initializer without initializing all stored properties the error. In other words, if you create a constructor of your own definition, Swift silently helps you to remove the Memberwise constructor, and your own con structor does not initialize the stored properties, which violates the syntax rules. But if you want both constructors (the Memberwise constructor and the custom constructor), you can write the custom constructsExtension Point {// custom initializer} inside.
Constructor inheritance designated constructor
The designated constructor is common in Swift, as the name implies, the constructor is the "prototype" of all constructors in your class. Only the designated constructor of the parent class is called in this constructor, or no other constructor is called the designated constructor . Each class must have at least one designated constructor, but you will see that there are cases where the designated constructor is declared in the class, because it is a subclass, and if you do not write any designated constructors, all designated constructors of the parent class are automatically inherited. We'll talk more about it in the following automatic constructor inheritance.
init(parameters){
// statments
}
Convenience constructors
The convenience constructor is the second type of constructor. It is primarily a horizontal proxy, meaning that there must exist in the convenience constructor, and only one constructor of that class is usually used toself.init(parameters)call a constructor of that class. Of course the convenience constructor is not necessary.
convenience init (parameters) {
// call a constructor in this class
self.init (parameters)
// customize properties
}
Constructor proxy rules for classes
- Rule 1: The designated constructor in a subclass must call the Desigated constructor of the last-level parent class
- Rule 2:convenience constructor must call another constructor in the same class
- The rule 3:convenience constructor calls a designated constructor through the call chain (proxy chain)
In conclusion, I will say
- The desingated constructor must always be up-proxy (that is, the designated constructor that invokes the nearest parent class)
- The convenience constructor must be a horizontal proxy, and the proxy endpoint is a desingated constructor
The following picture (quoted from Apple's official document) shows that the two points
The convenience constructor for subclass calls the second designated constructor (conforming to rule 2), and the second designated calls superclass's designated constructor (which conforms to Rule 1). This indicates that the convenience constructor is ultimately called the Designatedg Constructor (rule 3). The same is true of other constructor calls.
Here is another picture (quoted from Apple's official document)
Two-phase initialization
Each storage property in the first-stage class must have an initial value, and the second phase begins once the initial state of each stored-value attribute is determined. The second stage is the modification phase of the initial value before the new instance is available. The use of two-phase initialization allows for security of initialization, prevents property values from being accessed before initialization is complete, and property values are set to different values by another constructor. This is the same as OC, the only difference is OC in the first phase of the initial default value can only be 0 or nil
Initialize a security check mechanism
- Security Check 1: A designated constructor must initialize all storage properties defined in the class before it is proxied up
- Security Check 2: A designated constructor must first invoke the constructor of a parent class before modifying the property values of the parent class. If this is not the case, then the property value that you modify will be overwritten by the constructor of the parent class when the property is initialized.
- Security Check 3: A convenience constructor must invoke another constructor in this class before any property operation on this class, including properties of the parent class and properties defined by this class. If this is not the case, then the modified properties are likely to be overwritten by the constructor initialization properties in this class.
- Security Check 4: A constructor cannot invoke an instance method, read the value of any instance property, or use as a value point toselfknow the end of the first phase initialization
Two stages of initialization
First stage:
- A designated or convenience constructor is called in the class
- A new instance of the class requests a memory space to the system, but the memory has not yet been initialized
- A designated constructor for the class confirms that all the stored properties defined in the class have been initialized. The memory of these properties is initialized.
- The designated constructor tells the parent class constructor to perform the same action on the parent class's own properties
- Always acting to the highest level of the class inheritance chain
- Once the class inherits the highest level of the chain, and the final class on the chain confirms that all of its storage properties have been initialized, the instance memory is fully initialized, and then the first phase is complete.
The following picture is the first stage
Phase II:
- Starting at the top of the inheritance chain, each designated constructor can modify the property values in the instance, and the constructor can also access the self pointer, call the instance method, and so on.
- Finally, any convenience constructor on the inheritance chain can use the self pointer to modify the instance
The following picture is the second stage
The Swift Constructor explores