前言:前段時間想為系統類extension
一些init
方法,編譯器報錯不能為該類添加指定指定構造器,并讓我在init前添加convenience
,生成便利構造器。以此坑為契機,我對Swift的構造過程進行了一些了解。謹以此文記錄我對Swift構造器的理解。
說明:本文提及的構造器為類構造器,不涉及值構造器。
作用:
為自身和繼承來的存儲屬性賦初值。
構造器:
指定構造器:
類中必備的構造器,必須將類中的存儲屬性設置好值,必須至少有一個。有些子類可能不需要顯示聲明,默認繼承基類的指定構造器。
其語法為 :
init(參數名:參數類型) {
// 構造器的實現
}
便利構造器:
輔助構造器,通過調用指定構造器為屬性賦值,便利構造器不能和指定構造器方法同名、用 convenience 關鍵字聲明。
其語法為:
convenience init(參數名:參數類型) {
// 構造器的實現
}
可失敗構造器
一個類在構造過程中有可能失敗,則為其定義一個可失敗構造器。一個類可定義多個可失敗構造器,其語法為:
init?(參數名:參數類型) {
// 構造器的實現
}
//-------參考代碼:
class Person {
var name: String
var age: Int = 10
// MARK -- 指定構造器
init(name: String, age: Int) {
self.name = name
self.age = age
}
// MARK -- 便利構造器
convenience init() {
self.init(name: "jamalping", age: 11)
}
// MARK -- 可失敗構造器
init?(age: Int) {
guard age > 0 else {
return nil
}
self.age = age
self.name = "jamalping"
}
}
print(Person.init(age: -1) ?? "Person 初始化失敗") // 輸出為:Person 初始化失敗
必要構造器
在類的構造器前添加required修飾符表明所有該類的子類都必須實現該構造器:
其語法為:
required init(參數名:參數類型) {
// 構造器的實現
}
兩段式構造過程
一、1.確保當前類和父類所有存儲屬性都被初始化。
二、做一些其它初始化操作。
好處: 1.可以防止屬性在被初始化之前訪問, 2.可以防止屬性被另外一個構造器意外賦值
注意:構造器的初始化永遠是在所有類的第一階段初始化完畢之后才會開始第二階段
如下:
//-------參考代碼:
class Man: Person {
var weight: Int
init(weight: Int) {
print("初始化第一階段開始")
self.weight = weight
// 對父類的屬性進行初始化
super.init(name: "jamalping", age: 33)
print("初始化第二階段開始")
if self.age > 30 {
self.name = "jamal"
}
}
}
Man.init(weight: 100).name // 輸出結果為jamal```
##構造器鏈(指定構造器與便利構造器間的調用關系)
######規則:
1、指定構造器必須調用父類的指定構造器。
2、便利構造器必須調用同一類中其他的構造器。
3、便利構造器必須以調用一個指定構造器結束。
**總結**:指定構造器是向上調用的,便利構造器是橫向調用的。
//-------參考代碼:
class Person1 : Person {
var age: Int
var weight: Int = 100
init(age: Int) {
// 先初始化存儲屬性、再調用父類的指定構造器
self.age = age
super.init(name: "jamalping")
}
convenience init(age: Int, weight: Int) {
// 先調用指定構造器初始化self、再初始化其他屬性
self.init(weight: weight)
self.age = age
}
convenience init(weight: Int) {
self.init(age: 22, weight: weight)
}
}
構造器的繼承
Swift的子類不會默認繼承父類的構造器,滿足以下條件之一會自動繼承
1、子類沒有定義指定構造器
2、子類實現了父類的所有指定構造器
如下:兩種情況都滿足條件,所以子類自動繼承了父類的構造器
//-------參考代碼:
class Man: Person {
// 沒有定義指定構造器
}
class Women: Person {
//實現了父類的所有指定構造器
override init(name: String) {
super.init(name: name)
}
}
Man.init().name // name為"jamalping"
Women().name // name為"jamalping"
構造器的重寫
其語法為:
override init(參數名:參數類型) {
// 構造器的實現
}
class Man1: Person {
// 指定構造器的重寫
// 如果子類中的構造器和父類一模一樣, 必須加上override關鍵字, 表示重寫父類方法
// override init(name: String, age: Int) {
// super.init(name: name, age: age)
// self.name = "super man"
// }
// 將父類的指定構造器重寫成一個便利構造器, 也必須加上override關鍵字, 表示重寫父類方法
override convenience init(name: String, age: Int) {
self.init(name: name, age: age)
}
// 將父類的可失敗構造器重寫成指定構造器
// override init(age: Int) {
// super.init(name: "jamalping", age: age)
// }
// 將父類的可失敗構造器重寫成便利構造器
override convenience init(age: Int) {
self.init(name: "jamalping", age: age)
}
}
注意:
便利構造器不存在重寫
extension一個類的構造器,只能extension便利構造器