兩段式構(gòu)造過(guò)程
Swift 中類的構(gòu)造過(guò)程包含兩個(gè)階段抢腐。第一個(gè)階段旷档,每個(gè)存儲(chǔ)型屬性被引入它們的類指定一個(gè)初始值。當(dāng)每個(gè)存儲(chǔ)型屬性的初始值被確定后严里,第二階段開始新啼,它給每個(gè)類一次機(jī)會(huì),在新實(shí)例準(zhǔn)備使用之前進(jìn)一步定制它們的存儲(chǔ)型屬性刹碾。
兩段式構(gòu)造過(guò)程的使用讓構(gòu)造過(guò)程更安全燥撞,同時(shí)在整個(gè)類層級(jí)結(jié)構(gòu)中給予了每個(gè)類完全的靈活性。兩段式構(gòu)造過(guò)程可以防止屬性值在初始化之前被訪問迷帜,也可以防止屬性被另外一個(gè)構(gòu)造器意外地賦予不同的值物舒。
注意
Swift 的兩段式構(gòu)造過(guò)程跟 Objective-C 中的構(gòu)造過(guò)程類似。最主要的區(qū)別在于階段 1戏锹,Objective-C 給每一個(gè)屬性賦值0或空值(比如說(shuō)0或nil)冠胯。Swift 的構(gòu)造流程則更加靈活,它允許你設(shè)置定制的初始值锦针,并自如應(yīng)對(duì)某些屬性不能以0或nil作為合法默認(rèn)值的情況荠察。
Swift 編譯器將執(zhí)行 4 種有效的安全檢查置蜀,以確保兩段式構(gòu)造過(guò)程能不出錯(cuò)地完成:
安全檢查 1
指定構(gòu)造器必須保證它所在類引入的所有屬性都必須先初始化完成,之后才能將其它構(gòu)造任務(wù)向上代理給父類中的構(gòu)造器悉盆。
如上所述盯荤,一個(gè)對(duì)象的內(nèi)存只有在其所有存儲(chǔ)型屬性確定之后才能完全初始化。為了滿足這一規(guī)則焕盟,指定構(gòu)造器必須保證它所在類引入的屬性在它往上代理之前先完成初始化秋秤。
安全檢查 2
指定構(gòu)造器必須先向上代理調(diào)用父類構(gòu)造器,然后再為繼承的屬性設(shè)置新值脚翘。如果沒這么做灼卢,指定構(gòu)造器賦予的新值將被父類中的構(gòu)造器所覆蓋。
安全檢查 3
便利構(gòu)造器必須先代理調(diào)用同一類中的其它構(gòu)造器来农,然后再為任意屬性賦新值芥玉。如果沒這么做,便利構(gòu)造器賦予的新值將被同一類中其它指定構(gòu)造器所覆蓋备图。
安全檢查 4
構(gòu)造器在第一階段構(gòu)造完成之前灿巧,不能調(diào)用任何實(shí)例方法,不能讀取任何實(shí)例屬性的值揽涮,不能引用self作為一個(gè)值抠藕。
類實(shí)例在第一階段結(jié)束以前并不是完全有效的。只有第一階段完成后蒋困,該實(shí)例才會(huì)成為有效實(shí)例盾似,才能訪問屬性和調(diào)用方法。
以下是兩段式構(gòu)造過(guò)程中基于上述安全檢查的構(gòu)造流程展示:
階段 1
- 某個(gè)指定構(gòu)造器或便利構(gòu)造器被調(diào)用雪标。
- 完成新實(shí)例內(nèi)存的分配零院,但此時(shí)內(nèi)存還沒有被初始化。
- 指定構(gòu)造器確保其所在類引入的所有存儲(chǔ)型屬性都已賦初值村刨。存儲(chǔ)型屬性所屬的內(nèi)存完成初始化告抄。
- 指定構(gòu)造器將調(diào)用父類的構(gòu)造器,完成父類屬性的初始化嵌牺。
- 這個(gè)調(diào)用父類構(gòu)造器的過(guò)程沿著構(gòu)造器鏈一直往上執(zhí)行打洼,直到到達(dá)構(gòu)造器鏈的最頂部。
當(dāng)?shù)竭_(dá)了構(gòu)造器鏈最頂部逆粹,且已確保所有實(shí)例包含的存儲(chǔ)型屬性都已經(jīng)賦值募疮,這個(gè)實(shí)例的內(nèi)存被認(rèn)為已經(jīng)完全初始化。此時(shí)階段 1 完成僻弹。
階段 2
- 從頂部構(gòu)造器鏈一直往下阿浓,每個(gè)構(gòu)造器鏈中類的指定構(gòu)造器都有機(jī)會(huì)進(jìn)一步定制實(shí)例。構(gòu)造器此時(shí)可以訪問self蹋绽、修改它的屬性并調(diào)用實(shí)例方法等等芭毙。
- 最終筋蓖,任意構(gòu)造器鏈中的便利構(gòu)造器可以有機(jī)會(huì)定制實(shí)例和使用self。