Swift類的存儲型屬性必須在構(gòu)造過程完成后有值掠手,Swift為類提供了兩種構(gòu)造器——指定構(gòu)造器糊渊、便利構(gòu)造器
指定構(gòu)造器
init(參數(shù)表){
構(gòu)造過程
}
指定構(gòu)造器先完成自身類屬性值的初始化爷耀,再調(diào)用父類指定構(gòu)造器完成父類屬性值初始化申屹,一個類可以有多個指定構(gòu)造器蛮放,但至少要有一個(繼承的缩抡,默認(rèn)的都算)。在指定構(gòu)造器中不可以調(diào)用本類其他構(gòu)造器包颁,只能向上代理
便利構(gòu)造器
convenience init(參數(shù)表){
構(gòu)造過程
}
便利構(gòu)造器必須調(diào)用本類其他構(gòu)造器完成初始化瞻想,而且最終必須導(dǎo)致本類一個指定構(gòu)造器被調(diào)用,便利構(gòu)造器不可以直接調(diào)用父類構(gòu)造器娩嚼,只能橫向代理
總結(jié)為三條規(guī)則:
1蘑险、指定構(gòu)造器必須調(diào)用其直接父類(如果有)的指定構(gòu)造器(先初始化自己的屬性,然后調(diào)用父類的構(gòu)造器初始化父類的屬性)
2岳悟、便利構(gòu)造器必須調(diào)用本類中其他構(gòu)造器
3漠其、便利構(gòu)造器最終需要導(dǎo)致一個指定構(gòu)造器調(diào)用
指定構(gòu)造器必須總是向上代理,便利構(gòu)造器必須總是橫向代理
兩段式構(gòu)造過程
第一階段:
1、構(gòu)造器被調(diào)用
2和屎、分配內(nèi)存拴驮,未初始化
3、指定構(gòu)造器為本類存儲屬性賦初值柴信,本類存儲屬性完成初始化
4套啤、向上調(diào)用父類指定構(gòu)造器,重復(fù)類似3随常,4過程潜沦,直到頂部類
5、自下而上所有存儲屬性完成初始化绪氛,第一階段完成
第二階段:
1唆鸡、從頂部往下,每一層的指定構(gòu)造器都有機(jī)會進(jìn)一步定制本類實(shí)例枣察,此時構(gòu)造器可以訪問self争占,修改屬性,調(diào)用實(shí)例方法等序目,也就是說在未完全初始化時臂痕,實(shí)例是不可以使用的
2、最終猿涨,任意構(gòu)造器鏈中的便利構(gòu)造器都可以定制實(shí)例和使用self
編譯器進(jìn)行四種安全檢查保證上述構(gòu)造準(zhǔn)確進(jìn)行
- 指定構(gòu)造器先初始化本類的存儲屬性后握童,才可以向上代理給父類的指定構(gòu)造器
- 指定構(gòu)造器必須要在調(diào)用父類的指定構(gòu)造器后,才可以為繼承來的屬性賦新值叛赚,不然就被父類初始值覆蓋
- 便利構(gòu)造器必須先調(diào)用本類其他構(gòu)造器澡绩,才能為屬性賦新值,不然會被初始值覆蓋
- 構(gòu)造器在第一階段完成前俺附,不能調(diào)用實(shí)例方法英古,不能讀取實(shí)例屬性值,不能引用self作為一個值
默認(rèn)構(gòu)造器
默認(rèn)構(gòu)造器就是不帶參數(shù)的構(gòu)造器昙读,當(dāng)類中沒有提供任何構(gòu)造器時(繼承來的也算)召调,屬性都有默認(rèn)值時, 編譯器會提供一個默認(rèn)構(gòu)造器
class ABC{
var a:Int = 1
var b:Int = 2
var c:Int = 3
}
var abc = ABC()//編譯器會提供一個默認(rèn)的構(gòu)造器
print(abc.a,abc.b,abc.c)
class A {
init() {
}
}
沒有問題蛮浑,默認(rèn)就是這樣唠叛,我們寫了和默認(rèn)編譯器一樣的東西,也就是說我們可以自己定義指定型的默認(rèn)構(gòu)造器
class A {
convenience init() {
self.init()
}
}
編譯報(bào)init()重定義沮稚,便利構(gòu)造器不會阻止編譯器自動生成默認(rèn)構(gòu)造器艺沼,和默認(rèn)構(gòu)造器重名,所以報(bào)錯
class A {
var a:Int
init(a:Int) {
self.a = a
}
convenience init() {
self.init()
}
}
這段代碼編譯不報(bào)錯蕴掏,運(yùn)行階段調(diào)用init()
進(jìn)入死循環(huán)障般,我們有init(a:int)
调鲸,所以編譯器不會自動生成默認(rèn)構(gòu)造器,然后我們寫convenience init()
挽荡,也不會報(bào)錯藐石,奇怪的是構(gòu)造過程并不滿足三條規(guī)則中的規(guī)則三,因?yàn)橐呀?jīng)沒有了指定的默認(rèn)構(gòu)造器定拟,然而編譯器不報(bào)錯于微,運(yùn)行卻進(jìn)入死循環(huán),妥妥的編譯器bug
子類中訪問父類的屬性,用self
和super
都行