Swift construction process
The construction process is the preparation process for using an instance of a class, structure or enumeration type. This process includes setting initial values for each property in the instance and performing necessary preparation and initialization tasks.
Swift constructor uses init() method.
Unlike constructors in Objective-C, Swift's constructors do not need to return a value. Their main task is to ensure that new instances are properly initialized before they are used for the first time.
Class instances can also perform the work of cleaning up memory before the class instance is released by defining a deinitializer.
Initial assignment of stored attributes
When creating instances of classes and structures, appropriate initial values must be set for all stored attributes. .
When stored properties are assigned in the constructor, their values are set directly and no property observers are triggered.
The storage property assignment process in the constructor:
Create the initial value.
Specify default attribute values in attribute definitions.
Initialize the instance and call the init() method.
Constructor
The constructor is called when creating a new instance of a specific type. Its simplest form is similar to an instance method without any parameters, named after the keyword init.
Glossary
init() { // 实例化后执行的代码 }
Example
The following structure defines a constructor init without parameters, and initializes the values of the stored attributes length and breadth to 6. and 12:
struct rectangle { var length: Double var breadth: Double init() { length = 6 breadth = 12 } } var area = rectangle() print("矩形面积为 \(area.length*area.breadth)")
The execution output of the above program is:
矩形面积为 72.0
Default attribute value
We can set the initial value for the stored attribute in the constructor; Likewise, you can set a default value for a property when it is declared.
Using default values can make your constructor simpler and clearer, and the type of the property can be automatically deduced from the default value.
In the following example, we set the default value for the attribute when declaring it:
struct rectangle { // 设置默认值 var length = 6 var breadth = 12 } var area = rectangle() print("矩形的面积为 \(area.length*area.breadth)")
The output result of the execution of the above program is:
矩形面积为 72
Construction parameters
You can provide construction parameters when defining the constructor init(), as shown below:
struct Rectangle { var length: Double var breadth: Double var area: Double init(fromLength length: Double, fromBreadth breadth: Double) { self.length = length self.breadth = breadth area = length * breadth } init(fromLeng leng: Double, fromBread bread: Double) { self.length = leng self.breadth = bread area = leng * bread } } let ar = Rectangle(fromLength: 6, fromBreadth: 12) print("面积为: \(ar.area)") let are = Rectangle(fromLeng: 36, fromBread: 12) print("面积为: \(are.area)")
The output result of the above program execution is:
面积为: 72.0 面积为: 432.0
Internal and external parameters Name
The same as function and method parameters, construction parameters also have a parameter name used inside the constructor and an external parameter name used when calling the constructor.
However, constructors do not have a distinguishable name before the parentheses like functions and methods. Therefore, when calling a constructor, the constructor to be called is mainly determined by the parameter name and type in the constructor.
If you do not provide external names for parameters when defining a constructor, Swift will automatically generate an external name for each constructor parameter that is the same as the internal name.
struct Color { let red, green, blue: Double init(red: Double, green: Double, blue: Double) { self.red = red self.green = green self.blue = blue } init(white: Double) { red = white green = white blue = white } } // 创建一个新的Color实例,通过三种颜色的外部参数名来传值,并调用构造器 let magenta = Color(red: 1.0, green: 0.0, blue: 1.0) print("red 值为: \(magenta.red)") print("green 值为: \(magenta.green)") print("blue 值为: \(magenta.blue)") // 创建一个新的Color实例,通过三种颜色的外部参数名来传值,并调用构造器 let halfGray = Color(white: 0.5) print("red 值为: \(halfGray.red)") print("green 值为: \(halfGray.green)") print("blue 值为: \(halfGray.blue)")
The execution output of the above program is:
red 值为: 1.0 green 值为: 0.0 blue 值为: 1.0 red 值为: 0.5 green 值为: 0.5 blue 值为: 0.5
No external name parameter
If you do not want to provide an external name for a parameter of the constructor, you can use underscores _
to display the external name describing it.
struct Rectangle { var length: Double init(frombreadth breadth: Double) { length = breadth * 10 } init(frombre bre: Double) { length = bre * 30 } //不提供外部名字 init(_ area: Double) { length = area } } // 调用不提供外部名字 let rectarea = Rectangle(180.0) print("面积为: \(rectarea.length)") // 调用不提供外部名字 let rearea = Rectangle(370.0) print("面积为: \(rearea.length)") // 调用不提供外部名字 let recarea = Rectangle(110.0) print("面积为: \(recarea.length)")
The execution output of the above program is:
面积为: 180.0 面积为: 370.0 面积为: 110.0
Optional attribute type
If your customized type contains a stored attribute that logically allows a null value, you need to define it as an optional type (optional type) Select attribute type).
When a stored property is declared optional, it will be automatically initialized to empty nil.
struct Rectangle { var length: Double? init(frombreadth breadth: Double) { length = breadth * 10 } init(frombre bre: Double) { length = bre * 30 } init(_ area: Double) { length = area } } let rectarea = Rectangle(180.0) print("面积为:\(rectarea.length)") let rearea = Rectangle(370.0) print("面积为:\(rearea.length)") let recarea = Rectangle(110.0) print("面积为:\(recarea.length)")
The execution output of the above program is:
面积为:Optional(180.0) 面积为:Optional(370.0) 面积为:Optional(110.0)
Modify constant attributes during the construction process
As long as the value of the constant can be determined before the end of the construction process, you can Modify the value of a constant property at any point during construction.
For a class instance, its constant attributes can only be modified during the construction process of the class that defines it; they cannot be modified in subclasses.
Although the length attribute is now a constant, we can still set its value in the constructor of its class:
struct Rectangle { let length: Double? init(frombreadth breadth: Double) { length = breadth * 10 } init(frombre bre: Double) { length = bre * 30 } init(_ area: Double) { length = area } } let rectarea = Rectangle(180.0) print("面积为:\(rectarea.length)") let rearea = Rectangle(370.0) print("面积为:\(rearea.length)") let recarea = Rectangle(110.0) print("面积为:\(recarea.length)")
The output of the above program execution is:
面积为:Optional(180.0) 面积为:Optional(370.0) 面积为:Optional(110.0)
Default constructor
The default constructor will simply create an instance with all property values set to default values:
In the following example, all properties in the ShoppingListItem class have default values. , and it is a base class without a parent class, it will automatically obtain a default constructor that can set default values for all properties
class ShoppingListItem { var name: String? var quantity = 1 var purchased = false } var item = ShoppingListItem() print("名字为: \(item.name)") print("数理为: \(item.quantity)") print("是否付款: \(item.purchased)")
The output result of the above program execution is:
名字为: nil 数理为: 1 是否付款: false
Structure Member-by-member initializer
If structures provide default values for all stored properties and do not provide custom initializers themselves, they can automatically obtain a member-by-member initializer.
When we call the member-by-member constructor, we pass the parameter name that is the same as the member attribute name to complete the initial assignment of the member attributes.
The following example defines a structure Rectangle, which contains two attributes length and breadth. Swift can automatically deduce the type Double of these two properties based on their initial assignments of 100.0 and 200.0.
struct Rectangle { var length = 100.0, breadth = 200.0 } let area = Rectangle(length: 24.0, breadth: 32.0) print("矩形的面积: \(area.length)") print("矩形的面积: \(area.breadth)")
Since both stored properties have default values, the structure Rectangle automatically obtains a member-by-member constructor init(width:height:). You can use this to create new instances of Rectangle.
The execution output of the above program is:
名字为: nil 矩形的面积: 24.0 矩形的面积: 32.0
Constructor proxy of value type
The constructor can complete part of the construction process of the instance by calling other constructors. . This process is called constructor delegation, and it reduces code duplication across multiple constructors.
In the following example, the Rect structure calls the construction process of Size and Point:
struct Size { var width = 0.0, height = 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.height / 2) self.init(origin: Point(x: originX, y: originY), size: size) } } // origin和size属性都使用定义时的默认值Point(x: 0.0, y: 0.0)和Size(width: 0.0, height: 0.0): let basicRect = Rect() print("Size 结构体初始值: \(basicRect.size.width, basicRect.size.height) ") print("Rect 结构体初始值: \(basicRect.origin.x, basicRect.origin.y) ") // 将origin和size的参数值赋给对应的存储型属性 let originRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0)) print("Size 结构体初始值: \(originRect.size.width, originRect.size.height) ") print("Rect 结构体初始值: \(originRect.origin.x, originRect.origin.y) ") //先通过center和size的值计算出origin的坐标。 //然后再调用(或代理给)init(origin:size:)构造器来将新的origin和size值赋值到对应的属性中 let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height: 3.0)) print("Size 结构体初始值: \(centerRect.size.width, centerRect.size.height) ") print("Rect 结构体初始值: \(centerRect.origin.x, centerRect.origin.y) ")
The execution output of the above program is:
Size 结构体初始值: (0.0, 0.0) Rect 结构体初始值: (0.0, 0.0) Size 结构体初始值: (5.0, 5.0) Rect 结构体初始值: (2.0, 2.0) Size 结构体初始值: (3.0, 3.0) Rect 结构体初始值: (2.5, 2.5)
Constructor proxy rules
Value type | Class type |
---|---|
does not support inheritance, so the process of constructor proxies is relatively simple because they only Can proxy to other constructors provided by itself. You can use self.init to reference other initializers of the same value type in your custom constructor. | It can inherit from other classes, which means that the class is responsible for ensuring that all its inherited stored properties are initialized correctly during construction. |
Class inheritance and construction process
Swift provides two types of class constructors to ensure that stored properties in all class instances can obtain initial values. They are designated constructors and Convenience constructor.
Specified initializer | Convenience initializer |
The minor, auxiliary constructor in the class | |
Convenience initializers can be defined to call specified constructors in the same class and provide default values for their parameters. You can also define convenience initializers to create an instance for a special purpose or with specific inputs. | |
Provide convenience initializers for classes only when necessary | |