初始化
類屿岂、結(jié)構(gòu)體、枚舉都可以定義初始化器
類有2中初始化器:指定初始化器、便捷初始化器
每個類至少有一個指定初始化器诗充,指定初始化器是類的主要初始化器
默認初始化器總是類的指定初始化器
類偏向于少量指定初始化器,一個類通常只有一個指定初始化器
初始化器的相互調(diào)用規(guī)則
-- 指定初始化器必須從它的直系父類調(diào)用指定初始化器
-- 便捷初始化器必須從相同的類里調(diào)用另一個初始化器
-- 便捷初始化器最終必須調(diào)用一個指定初始化器
- 每個類至少有一個指定初始化器诱建,指定初始化器是類的主要初始化器
-- 指定初始化器必須從它的直系父類調(diào)用指定初始化器
兩段式初始化
Swift為了保證初始化過程的安全蝴蜓,設(shè)定了兩段式初始化、安全檢查
- 兩段式初始化
第一階段:初始化所有存儲屬性
1.外層調(diào)用指定\便捷初始化器
2.分配內(nèi)存給實例,但未初始化
3.指定初始化器確保當前定義的存儲屬性都初始化
4.指定初始化器調(diào)用父類的初始化器茎匠,不斷向上調(diào)用格仲,形成初始化器鏈
第二階段:設(shè)置新的存儲屬性值
1.從頂部初始化器往下,鏈中的每一個指定初始化器都有機會進一步定制實例
2.初始化器現(xiàn)在能夠使用self
3.最終诵冒,鏈中任何便捷初始化器都有機會定制實例以及使用self
在設(shè)置新的存儲屬性值或者其他定制化操作時凯肋,必須在第一階段結(jié)束后,才可以操作汽馋,編譯器在也在此基礎(chǔ)上禁止了在第一階段未結(jié)束前侮东,做定制化操作,保證了對象一定是初始化成功豹芯,且有值的悄雅。
重寫
當重寫父類的指定初始化器時,必須加上override
如果子類寫了一個匹配父類便捷初始化器的初始化器铁蹈,不用加上override
-- 因為子類是無法重寫父類的便捷初始化器
自動繼承
1.如果子類沒有自定義任何指定初始化器宽闲,它會自動繼承父類所有的指定初始化器
也就是說,可以直接使用父類初始化器
2.如果子類提供了父類所有指定初始化器的實現(xiàn)
要不就是第一種握牧,使用自動繼承容诬,要不就是使用重寫
3.就算子類添加了更多的便捷初始化器,這些規(guī)則仍然適用
4.子類以便捷初始化器的形式重寫父類的指定初始化器我碟,也可以作為滿足規(guī)則的一部分
required
用required修飾指定初始化器放案,表明其所有子類都必須實現(xiàn)該初始化器(通過繼承或者重寫實現(xiàn))
如果子類重寫了required初始化器,也不許加上required,不用加override
必須也加上required否則會報錯
屬性觀察器
- 父類的屬性在它自己的初始化器中賦值不會觸發(fā)屬性觀察器矫俺,但在子類的初始化器中賦值會觸發(fā)屬性觀察器
通過上述代碼可以看出吱殉,Person初始化器中是有賦值操作的,但是打印出來的觀察到的是1厘托,也就是說在繼承當中友雳,屬性觀察器,在初始化器中铅匹,注意是初始化器當中押赊,只會在子類的初始化器的賦值操作才會被回調(diào)。
可失敗初始化器
- 類包斑、結(jié)構(gòu)體流礁、枚舉都可以使用init?定義可失敗初始化器
寫返回nil直接報錯
給初始化器加上罗丰?號神帅,報錯消失
- 不允許同時定義參數(shù)標簽、參數(shù)個數(shù)萌抵、參數(shù)類型相同的可失敗初始化器和非可失敗初始化器
(不能重名)
雖然初始化器的內(nèi)容不一樣找御,但是在使用時會引起歧義元镀。
可以用 init! 定義隱私捷豹的可失敗初始化器
可失敗初始化器可以調(diào)用非可失敗初始化器,非可失敗初始化器調(diào)用可失敗初始化器需要進行解包
(因為可失敗初始化器就是一個可選項)如果初始化器調(diào)用一個可失敗初始化器導致初始化失敗霎桅,那么整個初始化過程都失敗栖疑,并且之后的代碼都停止執(zhí)行
(失敗會返回nil,那么肯定就蹦了呀滔驶,也可以寫一些失敗措施)可用一個非可失敗初始化器重寫一個可失敗初始化器遇革,但反過來是不行的
反初始化器 (deinit)
deinit叫做反初始化器,類似OC中的dealloc方法