swift類的兩段式構造過程

Paste_Image.png

前提

在理解兩段式構造函數之前,你首先要知道類的構造器分爲指定構造器便利構造器,並且要理解類的構造代理規則(可以簡單地理解爲類的指定構造方法和便利構造方法的相互調用限制)
以下是摘自The Swift Programming Language (3.1)

規則 1 指定構造器必須調用其直接父類的的指定構造器。
規則 2 便利構造器必須調用同類中定義的其它構造器。
規則 3 便利構造器必須最終導致一個指定構造器被調用。
一個更方便記憶的方法是:
• 指定構造器必須總是向上代理 
• 便利構造器必須總是橫向代理
• 指定構造器只能調用指定構造器(這一條是我加上的)

兩段式構造過程

兩段式構造過程與其說是一種規則倒不如說是一種思想

先分析下下面這個Demo再往下看:

class Foo {
    var a: Int?
    var b: Int?

    init() {
        a = 1
    }
}

class Bar: Foo {
    var c: Int?

    override init() {
        // 第一階段:初始化父類
        super.init() 

        // 第二階段:子類的Custom化
        b = 2
        c = 3
    }
}

let x = Bar()
x.a // 1
x.b // 2
x.c // 3

當你調用Bar()時,(1)首先會調用super.init()初始化父類,這時候類Foo的 屬性在自身的指定構造器中被初始化完成;(2)、一旦父類初始化完成,就可以初始化子類的屬性,並且可以客戶化定製子類的屬性,這裏個性化設置b=2,c=3

一、類的初始化規則

一個對象的內存只有在其所有存儲型屬性確定之後才能完全初始化

二、兩段式構造過程目的

1、讓構造過程更安全;
(說明:兩段式構造過程讓每個子類與父類都滿足了類的初始化規則)
2、在整個類層級結構中給予了每個類完全的靈活性。
(說明:在Bar的指定構造器中客戶化設置了 b=2,c=3,保證了每個類的靈活性)

三、兩段式構造過程兩個階段(對應着兩段式都早過程的目的)

第一階段、每個類在使用之前必須調用自身的指定構造器初始化每個存儲型屬性。
第二階段、新實例準備使用之前進一步定製它們的存 儲型屬性。

階段 1
• 某個指定構造器或便利構造器被調用。
• 完成新實例內存的分配,但此時內存還沒有被初始化。
• 指定構造器確保其所在類引入的所有存儲型屬性都已賦初值。存儲型屬性所屬的內存完成初始化。
• 指定構造器將調用父類的構造器,完成父類屬性的初始化。
• 這個調用父類構造器的過程沿着構造器鏈一直往上執行,直到到達構造器鏈的最頂部。
• 當到達了構造器鏈最頂部,且已確保所有實例包含的存儲型屬性都已經賦值,這個實例的內存被認爲已經完 全初始化。此時階段 1 完成。

階段 2
• 從頂部構造器鏈一直往下,每個構造器鏈中類的指定構造器都有機會進一步定製實例。構造器此時可以訪問 self 、修改它的屬性並調用實例方法等等。
• 最終,任意構造器鏈中的便利構造器可以有機會定製實例和使用 self 。

Paste_Image.png

四、安全性檢查

Swift 編譯器將執行 4 種有效的安全檢查,以確保兩段式構造過程能不出錯地完成:

安全檢查1:指定構造器必須先初始化當前類中定義的實例存儲屬性, 然後才能向上調用父類構造器
安全檢查2:指定構造器必須向上調用父類構造器, 然後才能對繼承得到的屬性賦值
安全檢查3:便利構造器必須先調用同一個類的其他構造器, 然後才能對屬性賦值
安全檢查4:構造器在第一階段完成之前, 不能調用實例方法, 不能讀取實例屬性

不懂就藥問

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章