1. Initializer

1.1 Initializers are called when a particular type is created

struct Fathrenheit {

var temperture : Double

init() {
   temperture = 32
}
}

var f = Fathrenheit()

print("The default temperature is \(f.temperture) fathreheit")
Copy the code

1.2. Default property values

As mentioned above, you can set initial values for storage properties in the initializer. Also, specify a default property value as part of the property declaration. The default attribute value can be specified by assigning an initial value to the attribute when it is defined

Struct temperture {var temperture = 32.0} var f = Fathrenheit() print("The temperature is \(f emperture) fathreheit")Copy the code

1.3. Default initializer

Swift provides a default initializer for all structures or classes that do not provide an initializer to provide default values for all attributes. The default initializer simply creates a new instance with default values for all properties

class ShoppingListItem {
  var name : String?
  var quantity = 1
  var purchased = **false**
}

**var** item = ShoppingListItem()
Copy the code

1.4 Custom initializers

You can provide initialization form parameters as part of the initializer to define the type and value name during initialization. Initializing formal parameters has the same functionality and syntax as formal parameters of functions and methods

struct Celsius { var temperatureInCelsius: Double init(fromFathrenheit fahtenheit: 1){temperatureInCelsius = (fahtenheit - 32.0) / 1.8} init(formKelvin Kelvin :Double) {temperatureInCelsius = Kelvin - 237.15}} Let boilingPointOfWater = Celsius(formKelvin: 212.0) Let freezingPointOfWater = Celsius(formKelvin: 212.0) 273.15)Copy the code

1.5. Assign constant properties in initialization

A constant property can be assigned a value at any time of initialization, as long as it is set to a certain value at the end of initialization. Once a constant property is assigned a value, it cannot be modified

class SurveQuestion { let text: String var response : String? init(text : String) { self.text = text } func ask() { print(text) } } let beetQuestion = SurveQuestion(text: "How about beets?" ) beetQuestion.ask() beetQuestion.response = "I also like beets.(But nor with cheese)"Copy the code

2. Structure member initializer

If a structure type does not define any custom initializers, it automatically gets a member initializer. Unlike the default initializer, an architect accepts a member initializer even if its storage properties do not have default values

Struct size {var width = 0.0,heighr = 0.0} let twoByTwo = size(width: 2.0, Heighr: 2.0)Copy the code

3. Initializer delegates for value types

Initializers can call other initializers to perform initialization of partial instances. This process, known as initializer delegation, avoids redundant code in multiple initializers

Struct Size {var width = 0.0,heighr = 0.0} struct Point {var x = 0.0,y = 0.0} struct Rect {var origin = Point() var size = Size() init() { } init(origin : Point , size : Size) { self.origin = origin self.size = size } init(center:Point,size:Size) { let originX = center.x - (size.width / 2)  let originY = center.y - (size.heighr / 2) self.init(origin: Point(x:originX,y:originY), size: size) } }Copy the code

4. Class inheritance and initialization

4.1 Description

  1. Store attributes for all classes (including all attributes inherited from their parent class). Must be assigned initial values during initialization
  2. Swift defines two initializers for types to ensure that all storage attributes accept an initial value. These are called designated initializers and convenient initializers
  3. Specifies that the initializer is the primary initializer for the class. The specified initializer initializes all attributes referenced by that class and calls the appropriate parent initializer to continue the initialization process to the parent chain
  4. Classes tend to have a small number of designated initializers, and a class usually has only one. The specified initializer is the “transport” point at which initialization begins to continue the initialization process to the parent chain
  5. Each class must have at least one designated initializer, as described in automatic inheritance of initializers. In some cases, these requirements are met by inheriting one or more designated initializers from the parent class
  6. The convenience initializer is secondary. It is possible to define a convenience initializer in the same class to call a specified initializer as a convenience initializer to set default formal parameters to the specified initializer. An instance of this class can also be created by defining a convenience initializer for a specific usage or input value type
  7. Don’t provide a convenient initializer if your class doesn’t need one. Use convenient initializers when creating shortcuts to common initialization patterns to save money or to make class initialization clearer

4.2. Specify initializers and convenient initializers

init(parameters) {
    statements
}

convenience** init(parameters){
    statements
}
Copy the code

4.3. Class initialization delegate

The specified initializer must call the specified initializer from its immediate parent

The convenience initializer must call another initializer from the same class

The convenience initializer must eventually call an initializer

4.4 Two-stage Initialization

Class initialization for Swift is a two-step process. In the first phase, each storage attribute is assigned an initial value by the imported class. Once the initial state of each storage property is determined, the second one begins, and each class has the opportunity to customize its storage properties before the new instance is ready.

The use of a two-stage initialization process makes initialization safer, while the hierarchical structure of each class gives complete flexibility. The two-step initialization process prevents the property from being accessed before the initializer and also prevents the property from being accidentally assigned a different value by another initializer

The security check

1. The specified initializer must ensure that all attributes introduced by its class are initialized before delegating to the parent initializer

2. Specify that the initializer must delegate to the parent class initializer before setting new values for inherited properties. If you do not, the new value assigned by the specified initializer will be overwritten by the initializer in the parent class

3. Convenience initializers must delegate to other initializers of the class before assigning any attributes (including those defined in the class). If this is not done, the new value assigned by the convenient constructor initializer will be overridden by other specified initializers in its own class

4. The initializer cannot call any instance methods, read any instance attribute values, or reference self as a value until the first stage of initialization is complete

class Peson { var name : String var age : Int init(name:String,age:Int) { self.name = name self.age = age } convenience init() { self.init(name: "[Unnamed]", age: 0) } } class Teacher : Peson { var salary : Int init (name: String, age: Int, salary: Int) {/ * self. Salary = salary: designated initializer must ensure that before upward entrusted to the parent class initializer, */ self.salary = salary super.init(name: name, age: age) Age) /* self.name = name + "teacher" : specifies that the initializer must first delegate to the parent initializer, */ self.name = name + "teacher" self.test()} Convenience override init(name: String, age: Int) {self.init(name: name, age: 30, salary: 5000) /* self.name = name + "teacher ": Convenient initializers must first delegate to other initializers in their class, */ self.name = name + "teacher"} func test() {print(" I am a teacher")} func showInfo() { print("teacher name \(name),age \(age), salary \(salary)") } }Copy the code
6.4.4.1. Phase one

The specified or convenient initializer is called in the class

Memory allocation for a new instance of this class. Memory has not been initialized

3. The designated initializer for this class ensures that all storage attributes introduced by this class have a value. Now the memory where these properties are stored is initialized

4. The parent initializer is called up the chain of initializers until the very top of the initializer is reached

5. Once the top of the initializer chain is reached, the class at the top of the chain ensures that all storage properties have a value, and the memory of this instance is considered fully initialized, at which point the first phase is complete

6.4.4.2. Phase two

1. From the top initializer down, each designated initializer in the chain has the opportunity to further customize instances. The initializer now has access to self and can modify its properties, call its instance methods, and so on

2. Finally, any convenient initializer in the chain has the opportunity to customize instances and use Self

6.5. Inheritance and override of initializers

  • Unlike subclasses in OC, subclasses of Swift do not inherit their parent class’s initializer by default. This mechanism prevents the simple initializer of the parent class from being inherited by a dedicated subclass and used to create a new instance that is completely misinitialized. The initializer of the parent class is inherited only under certain circumstances.
  • If you want to customize a subclass to implement the same initialization as one or more parent classes, you can provide custom implementations for those initializers in the subclass
  • When you write a subclass initializer that matches the parent class specified initializer, you can actually override that initializer. Therefore, the Override modifier must be written before the subclass’s initializer definition. Even automatically provided default initializers can be overridden as described by default initializers

6.5.1. Automatic inheritance of initializers

Rules:

  • If a subclass does not define any initializers, it automatically inherits the specified initializers from its parent class
  • If a subclass provides implementations of all of its superclass specified initializers — either inherited through rule 1 or by providing a custom implementation in the definition — then it automatically inherits all of its superclass convenience initializers

6.5.2. Fail initializer

  • Defining classes, structs, or enumerations that can fail initialization can be useful in some cases. This failure can occur in several ways, including passing invalid parameters to initialization, or missing some external required resource, or other circumstances that prevent initialization
  • To handle this possible failure, define one or more failable initializers in a class or structure. Add the question mark (init?) after the init keyword. To write
6.5.3. Initializer must be used

Add the required modifier to the class initializer to indicate that all subclasses of the class must implement the initializer

6.6. De-initialization

  • The backinitializer is called immediately when an instance of the class is released. You can write de-initializers using the deninit keyword, just as you would write initializers using the init keyword. De-initializers are valid only in class types
  • The backinitializer is automatically called before the instance is released. The backinitializer cannot be called by itself. A parent’s de-initializer can be inherited by a subclass, and a subclass’s de-initializer will always be called, even if the subclass doesn’t have a de-initializer
  • There can only be one de-initializer per class. The backinitializer accepts no arguments of any kind and does not need to write parentheses