認(rèn)識Swift系列13之對象初始化

Swift中初始化器:

  • 指定初始化器(designated initializer)
  • 便捷初始化器(convenience initializer)

初始化器定義

 // 指定初始化器
 init(parameters) {
    statements
 }
 // 便捷初始化器
 convenience init(parameters) {
    statements
 }

通常每個(gè)類的初始化器有如下特點(diǎn)

1.每個(gè)類至少有一個(gè)指定初始化器淤刃,指定初始化器是類的主要初始化器
2.默認(rèn)初始化器總是類的指定初始化器
3.類偏向于指定初始化器讯壶,一個(gè)類通常只有一個(gè)指定的初始化器

關(guān)于指定初始化器和便利初始化器關(guān)系荠雕,有以下三個(gè)原則

1.指定初始化器必須調(diào)用它的直接直系父類指定初始化器
2.便捷初始化器必須調(diào)用本類的另一個(gè)初始化器(可以使便利或指定)
3.編輯初始化器“最終”必須調(diào)用一個(gè)指定初始化器(這里的最終是指調(diào)用鏈的尾端必須調(diào)用指定初始化器)

一、初始化器的調(diào)用規(guī)則

  • 指定初始化器:縱向調(diào)用
  • 便利初始化器:橫向調(diào)用

縱向調(diào)用:指子類指定初始化器調(diào)用父類指定初始化器(指定初始化器之間不能相互調(diào)用)
橫向調(diào)用:指本類內(nèi)部相互調(diào)用(便利初始化器可以調(diào)用便利和指定初始化器)

構(gòu)造器調(diào)用鏈
第一階段:初始化所有存儲屬性
1.外層調(diào)用指定狐赡、便捷初始化器
2.分配內(nèi)存給實(shí)例(有了存儲空間唯竹,但未初始化沸停,空間內(nèi)是垃圾數(shù)據(jù))
3.指定初始化器確保當(dāng)前類的存儲屬性都被初始化
4.指定初始化器調(diào)用父類的初始化器辆影,不斷向上,形成初始化器鏈

第二階段:設(shè)置新的存儲屬性
1.從頂部初始化器向下后添,鏈中的每一個(gè)指定初始化器都有機(jī)會進(jìn)一步定制實(shí)例
2.此時(shí)初始化器能夠使用self(訪問笨枯、修改屬性,調(diào)用實(shí)例方法等等)
3.最終遇西,鏈中任何便捷初始化器都有機(jī)會定制實(shí)例以及使用self

二馅精、初始化器的調(diào)用規(guī)則

  • 1.指定初始化器之間不能相互調(diào)動

一個(gè)指定初始化器意味著一條特定的業(yè)務(wù)場景線,所以相互之間不能調(diào)用

如下一個(gè)類粱檀,有兩個(gè)指定初始化器init(age: Int, name: String)init(age: Int),這兩個(gè)初始化器之間是不能調(diào)用的洲敢,因?yàn)槌跏蓟螽a(chǎn)生的業(yè)務(wù)場景并不同

class Object {
    var age = 10
    var name = "Rose"
    
    init(age: Int, name: String) {
        self.age = age
        self.name = name
    }
    
    init(age: Int) {
        self.age = age
        self.name = "Jack"
    }
}

2.便利初始化器可以調(diào)用指定初始化器,也可以調(diào)用便利初始器(此情況最終傳遞到指定初始化器)

如下初始化器的傳遞情況init()-->init(age: Int)-->init(age: Int, name: String),雖然前兩個(gè)初始化器都是便利初始化器梧税,但最終落腳點(diǎn)是指定初始化器

class Object {
    var age = 10
    var name = "Rose"
    
    init(age: Int, name: String) {
        self.age = age
        self.name = name
    }
    
    convenience init(age: Int) {
        self.init(age: 10, name: "Jack")
    }
    
    convenience init() {
        self.init(age: 10)
    }
}

三沦疾、初始化器繼承

  • 當(dāng)子類不寫任何初始化器的時(shí)候,默認(rèn)繼承父類所有初始化器
  • 當(dāng)子類不寫任何指定初始化器的時(shí)候第队,默認(rèn)繼承父類所有初始化器
class Object {
    var age = 10
    var name = "Rose"
    
    init(age: Int, name: String) {
        self.age = age
        self.name = name
    }
    
    convenience init(age: Int) {
        self.init(age: 10, name: "Jack")
    }
    
    convenience init() {
        self.init(age: 10)
    }
}

class Person: Object {
    var sex = true
    
    convenience init(sex: Bool) {
        self.init()
        self.sex = sex
    }
    convenience init(sex: Bool, name: String) {
        self.init(age: 20)
        self.sex = sex
    }
}

這里的Person實(shí)際上已經(jīng)默認(rèn)繼承了Object的所有初始化器哮塞,這里Person擁有5個(gè)初始化器

  • 當(dāng)子類有自定義初始化器的時(shí)候,不會繼承父類初始化器(包括指定和便利)
class Object {
    var age = 10
    var name = "Rose"
    
    init(age: Int, name: String) {
        self.age = age
        self.name = name
    }
    
    convenience init(age: Int) {
        self.init(age: 10, name: "Jack")
    }
    
    convenience init() {
        self.init(age: 10)
    }
}


class Person: Object {
    var sex = true
    
    init() {
        super.init(age: 20, name: "sss")
    }
    
    convenience init(sex: Bool) {
        self.init()
        self.sex = sex
    }
}

這里的Person沒有繼承Object的所有初始化器凳谦,Person只有本身的2個(gè)初始化器

  • 當(dāng)子類沒有新的指定初始化器忆畅,但是重寫了父類的指定初始化器的時(shí)候,此時(shí)父類的所有初始化構(gòu)造器都會被繼承下來

便捷初始化器不能重寫尸执,也就是子類不能夠重寫家凯,嚴(yán)格意義上來說不能算繼承

class Object {
    var age = 10
    var name = "Rose"
    
    init(age: Int, name: String) {
        self.age = age
        self.name = name
    }
    
    convenience init(age: Int) {
        self.init(age: 10, name: "Jack")
    }
    
    convenience init() {
        self.init(age: 10)
    }
}


class Person: Object {
    var sex: Bool
    
    override init(age: Int, name: String) {
        sex = false
        super.init(age: age, name: name)
    }
}

這里的Person繼承了Object的所有初始化器,這里Person擁有3個(gè)初始化器

三如失、兩段式初始化

所有分段式初始化绊诲,即一個(gè)初始化函數(shù)的內(nèi)部初始化過程分為兩段(三個(gè)步驟)

  1. 初始化自己所有存儲屬性
  2. 調(diào)用父類初始化方法super.init()
  3. 個(gè)性化定制(為成員變量重新賦值、調(diào)用成員方法等)
init(sex: Bool, id: String) {
    // 1. 初始化自己所有存儲屬性
    self.sex = sex
    self.id = id
    
    // 調(diào)用父類初始化方法
    super.init(age: 10, name: "Jack")
    
    // 3. 個(gè)性化定制
    self.age = 20
    self.name = "Jack1"
    self.test()
}

swift為了安全性更上一個(gè)等級褪贵,設(shè)計(jì)了這樣一個(gè)兩段式結(jié)構(gòu)掂之,過程體現(xiàn)如下

初始化屬性:子類-->父類-->...-->基類
個(gè)性化定制:基類-->...-->父類-->子類

原理上來說,運(yùn)用了棧的結(jié)構(gòu)思想脆丁,保證了:

1.所有繼承鏈上的成員變量能夠被初始化到
2.指定初始化器形成調(diào)用鏈
3.個(gè)性化定制一定在類完全初始化之后

四世舰、安全檢查

  • 指定初始化器必須在保證調(diào)用父類初始化器之前,必須保證本類所有存儲屬性都要初始化完成
  • 指定初始化器必須在調(diào)用父類初始化器之后槽卫,才能為繼承的屬性設(shè)置新值
  • 便捷初始化器必須先調(diào)用同類中國的其它指定初始化器之后跟压,才能為任意屬性設(shè)置新值
  • 初始化器在1階段完成之前不能訪問self、屬性即調(diào)用實(shí)例方法
  • 直到階段1結(jié)束歼培,才能算初始化過程合法

五震蒋、重寫

  • 當(dāng)重寫父類的指定初始化器時(shí)茸塞,必須加上override(即使子類的實(shí)現(xiàn)是便捷初始化器)
  • 如果子類寫了一個(gè)匹配父類便捷初始化器的初始化器,不用加上override因?yàn)楦割惖谋憬莩跏蓟饔肋h(yuǎn)不會通過子類直接調(diào)用喷好,因此翔横,嚴(yán)格來說读跷,子類無法重寫父類的便捷初始化器

六梗搅、自動繼承

  • 1.如果子類沒有定義任何指定初始化器,它會自動繼承父類所有的指定初始化器
  • 2.如果子類提供了父類所有指定初始化器的實(shí)現(xiàn)(要么通過方式1繼承效览,要么重寫)无切,那么子類自動繼承所有的父類便捷初始化器
  • 3.就算子類添加了更多的便捷初始化器,這些規(guī)則仍然適用
  • 4.子類以便捷初始化器的形式重寫父類的指定初始化器丐枉,也可以作為滿足規(guī)則2的一部分

總結(jié)

  • 1.初始化器必須滿足分段規(guī)則
  • 2.只要之類沒有自定義新的 指定 初始化器(繼承和重寫得來的不算)哆键,子類擁有父類所有初始化器
  • 3.便捷初始化方法內(nèi)部不能使用super調(diào)用父類初始化器,只能使用self調(diào)用本身擁有或繼承得來的
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瘦锹,一起剝皮案震驚了整個(gè)濱河市籍嘹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌弯院,老刑警劉巖辱士,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異听绳,居然都是意外死亡颂碘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門椅挣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來头岔,“玉大人,你說我怎么就攤上這事鼠证∠靠ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵量九,是天一觀的道長适掰。 經(jīng)常有香客問我,道長娩鹉,這世上最難降的妖魔是什么攻谁? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮弯予,結(jié)果婚禮上戚宦,老公的妹妹穿的比我還像新娘。我一直安慰自己锈嫩,他們只是感情好受楼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布垦搬。 她就那樣靜靜地躺著,像睡著了一般艳汽。 火紅的嫁衣襯著肌膚如雪猴贰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天河狐,我揣著相機(jī)與錄音米绕,去河邊找鬼。 笑死馋艺,一個(gè)胖子當(dāng)著我的面吹牛栅干,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播捐祠,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼碱鳞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了踱蛀?” 一聲冷哼從身側(cè)響起窿给,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎率拒,沒想到半個(gè)月后崩泡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俏橘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年允华,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寥掐。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡靴寂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出召耘,到底是詐尸還是另有隱情百炬,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布污它,位于F島的核電站剖踊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏衫贬。R本人自食惡果不足惜德澈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望固惯。 院中可真熱鬧梆造,春花似錦、人聲如沸葬毫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至忽肛,卻和暖如春村砂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背屹逛。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工础废, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人煎源。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓色迂,卻偏偏與公主長得像香缺,于是被迫代替她去往敵國和親手销。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353