Swift類的初始化

在swift中,對象的初始化和oc中類似,分為兩個階段爆办,一個階段是對象的內(nèi)存分配,另一個階段是對對象中的store value進(jìn)行初始化课梳。不過第一個階段和oc略有不同距辆,oc在第一階段分配內(nèi)存后余佃,會將所有的屬性設(shè)為0或者null,而swift則更為靈活跨算,可以指定一些除0以外的值爆土。

全能初始化方法和便利初始化方法

在詳細(xì)分析兩段式(two-phrase)初始化之前,先了解一下swift中兩種初始化方法:全能初始化方法(designated initializier)和便利初始化方法(convenience initializer)诸蚕。

全能初始化方法

就像其名字一樣步势,通過全能初始化方法來初始化一個對象后,其所有的store property都能夠進(jìn)行初始化背犯。一個類可以有多個全能初始化方法坏瘩,但是一般來說只有一個。只要保證全能初始化方法能夠初始化所有屬性即可漠魏。

class GameCharacter {
    var weapon: String
    
    init() {
        self.weapon = "fist"
    }
    
    init(weapon: String) {
        self.weapon = weapon
    }
}

如上倔矾,Person類有兩個全能初始化方法,一個init()柱锹,一個是init(name: String)哪自,每個初始化方法都能夠?qū)ame進(jìn)行初始化。

如果不在初始化方法中對非可選值的屬性進(jìn)行初始化禁熏,編譯器會提示未初始化的錯誤提陶。

便利初始化方法

便利初始化方法則只是初始化類中部分屬性∑ゲ悖看以下代碼

class Warrior: GameCharacter {
    var shield: String
    
    init(weapon: String, shield: String) {
        self.shield = shield
        super.init(weapon: weapon)
    }
    
    convenience init(shield: String) {
        self.init(weapon: "fist", shield: shield)
    }
}

Warrior有一個全能初始化方法init(weapon: String, shield: String隙笆,這個初始化方法可以初始化所有的屬性,也就是shield和從父類繼承來的weapon升筏。另外還有一個便利初始化方法init(shield: String)撑柔,該方法只顯示指定了shield的值,而weapon的值則是提供一個默認(rèn)的值您访。我們注意到在這個初始化方法在前面加了一個關(guān)鍵字convenience铅忿。這個convenience除了表明這個方法是便利初始化方法外,還有一個作用就是讓編譯器進(jìn)行一些錯誤檢查灵汪。

全能初始化方法和便利初始化方法之間的調(diào)用規(guī)則

全能初始化方法和便利初始化方法調(diào)用規(guī)則有三個

  • 全能初始化方法必須調(diào)用父類的全能初始化方法
  • 便利初始化方法只能調(diào)用當(dāng)前類的初始化方法檀训,不能調(diào)用父類的初始化方法
  • 便利初始化方法,最終必須調(diào)用當(dāng)前類的全能初始化方法享言。

下圖可以很直觀的表明這三個規(guī)則:

image 1

類的兩段式初始化

swift和oc最大的區(qū)別峻凫,除了多了很多新的特性,比如新的枚舉類型览露,struct類型等荧琼,最明顯的區(qū)別就是在編譯器上面。swift的編譯器在編譯期間做了很多的安全檢查工作,比如對于一個可能為nil的值命锄,必須進(jìn)行解包堰乔;兩個不同類型的變量不能相互進(jìn)行賦值(即使是Double和Int之間的也不能隱式轉(zhuǎn)換)。類的初始化方法也一樣脐恩。

在類的初始化方法中镐侯,有四個安全性的檢查:

  • 全能初始化方法必須確保在父類被初始化之前,所有的屬性被正確初始化
  • 再給被繼承的屬性賦值之前驶冒,必須調(diào)用父類的全能初始化方法苟翻,也就是說,父類必須被初始化之后才能給被集成的屬性賦值
  • 便利初始化方法在對屬性賦值之前只怎,必須調(diào)用其它初始化方法
  • 在當(dāng)前類沒有被正確初始化之前(即第一階段),不能調(diào)用類的實例方法和讀取實例屬性

下面這段代碼說明了這四個檢查

class Warrior: GameCharacter {
    var shield: String
    
    init(weapon: String, shield: String) {
        self.shield = shield // 在調(diào)用父類之前怜俐,必須對初始化本類的屬性
//        attack() 編譯器錯誤身堡,當(dāng)前類還沒初始化完成,不能調(diào)用實例方法
        super.init(weapon: weapon)
        self.weapon = "sword" //在父類初始化完成后拍鲤,才能對從父類集成的屬性進(jìn)行賦值
    }
    
    convenience init(shield: String) {
        self.init(weapon: "fist", shield: shield)
        self.shield = "silver shield" //便利初始化方法在調(diào)用其它初始化方法后贴谎,才能對屬性進(jìn)行賦值
    }
    
    func attack() {
        Swift.print("use \(weapon) to attack")
    }
}

如果以上四個檢查任何一個不符合,編譯器都會報錯季稳。

而swift的兩段式初始化正式基于這四個安全檢查的擅这,下面來看看這兩個階段分別作了什么

第一階段

  • 調(diào)用全能初始化方法或者便利初始化方法,系統(tǒng)分配內(nèi)存景鼠,但是并未對這個類進(jìn)行初始化
  • 在全能初始化方法中初始化所有屬性
  • 調(diào)用父類的全能初始化方法執(zhí)行前兩個相同的步驟
  • 沿著繼承鏈不斷向上一直到根類為止
  • 這個時候在繼承鏈上的類都被正確的初始化仲翎,第一階段完成

第二階段

  • 從根類開始向下返回,每個類的全能初始化方法都能夠進(jìn)行更多的對類的初始化操作铛漓,包括可以使用屬性溯香,可以調(diào)用實例方法
  • 最后,任何便利方法都有機會去對類進(jìn)行更多的初始化

沿用上一個代碼片段浓恶,當(dāng)調(diào)用init(weapon: String, shield: String)時玫坛,第一階段的初始化就開始了,直到GameCharacter的全能初始化方法中的self.weapon = "fist"包晰,這時候第一階段結(jié)束湿镀。然后再沿著繼承鏈向下,直到Warrior類的全能初始化方法中的self.weapon = "sword時伐憾,第二階段結(jié)束勉痴。

我們可以看到,swift的二段式初始化能夠保證我們在使用一個類的時候能夠被正確的初始化树肃,而且這個過程都是在編譯時檢查的蚀腿,這樣就能夠確保我們在編寫類的初始化代碼的時候不會犯錯。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市莉钙,隨后出現(xiàn)的幾起案子廓脆,更是在濱河造成了極大的恐慌,老刑警劉巖磁玉,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件停忿,死亡現(xiàn)場離奇詭異,居然都是意外死亡蚊伞,警方通過查閱死者的電腦和手機席赂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來时迫,“玉大人颅停,你說我怎么就攤上這事÷尤” “怎么了癞揉?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長溺欧。 經(jīng)常有香客問我喊熟,道長,這世上最難降的妖魔是什么姐刁? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任芥牌,我火速辦了婚禮,結(jié)果婚禮上聂使,老公的妹妹穿的比我還像新娘壁拉。我一直安慰自己,他們只是感情好柏靶,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布扇商。 她就那樣靜靜地躺著,像睡著了一般宿礁。 火紅的嫁衣襯著肌膚如雪案铺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天梆靖,我揣著相機與錄音控汉,去河邊找鬼。 笑死返吻,一個胖子當(dāng)著我的面吹牛姑子,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播测僵,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼街佑,長吁一口氣:“原來是場噩夢啊……” “哼谢翎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎囚戚,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體褒侧,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年谊迄,在試婚紗的時候發(fā)現(xiàn)自己被綠了闷供。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡统诺,死狀恐怖歪脏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情粮呢,我是刑警寧澤婿失,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站鬼贱,受9級特大地震影響移怯,放射性物質(zhì)發(fā)生泄漏香璃。R本人自食惡果不足惜这难,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望葡秒。 院中可真熱鬧姻乓,春花似錦、人聲如沸眯牧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽学少。三九已至剪个,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間版确,已是汗流浹背扣囊。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绒疗,地道東北人侵歇。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像吓蘑,于是被迫代替她去往敵國和親惕虑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 官方文檔 初始化 Initialization是為準(zhǔn)備使用類,結(jié)構(gòu)體或者枚舉實例的一個過程溃蔫。這個過程涉及了在實例里...
    hrscy閱讀 1,136評論 0 1
  • 初始化(Initialization) 初始化是類健提、結(jié)構(gòu)體、枚舉類型的準(zhǔn)備過程酒唉。這個過程涉及到所有存儲屬性的初始化...
    泗哥閱讀 5,634評論 0 3
  • 初始化 (Initialization) 自從蘋果2014年發(fā)布Swift矩桂,到現(xiàn)在已經(jīng)兩年多了,而Swift也來到...
    Lebron_James閱讀 1,210評論 0 0
  • 123.繼承 一個類可以從另外一個類繼承方法,屬性和其他特征痪伦。當(dāng)一個類繼承另外一個類時, 繼承類叫子類, 被繼承的...
    無灃閱讀 1,392評論 2 4
  • Eureka客戶端常用配置 eureka.client.enabled=true——啟用Eureka客戶端侄榴,默認(rèn)t...
    zlup閱讀 1,458評論 0 2