Swift3.0初始化(Initialization)

和 OC 的不同,Swift中的構(gòu)造器(Initializers) 不需要返回一個(gè)值脓钾。它們的主要功能就是確保新的實(shí)例在第一次使用前完成正確的初始化。

存儲(chǔ)值的初始賦值(Setting Initial Values for Stored Properties)

類(lèi)和結(jié)構(gòu)體必須要?jiǎng)?chuàng)建的時(shí)候?qū)λ鼈兊拇鎯?chǔ)屬性進(jìn)行合適的賦值桩警。存儲(chǔ)值不能處于一個(gè)未知的狀態(tài)可训。

可以在構(gòu)造器中為存儲(chǔ)型屬性賦值,也可以在定義屬性時(shí)為其賦值捶枢。

構(gòu)造器(Initializers)

構(gòu)造器就是在創(chuàng)建某個(gè)特定類(lèi)型的新實(shí)例時(shí)被調(diào)用握截,最簡(jiǎn)單的形式就是不帶任何參數(shù):

init() {
    // 構(gòu)造過(guò)程
}
Initializers ??

默認(rèn)屬性值(Default Property Values)

注意
如果一個(gè)屬性總是使用相同的初始值,那么就應(yīng)該設(shè)置一個(gè)默認(rèn)值烂叔,而不是在構(gòu)造器中賦值谨胞。雖然效果是一樣的,但是前者個(gè)簡(jiǎn)潔蒜鸡、清晰胯努,并且可以自動(dòng)推到出類(lèi)型牢裳。同時(shí),也能充分利用到默認(rèn)構(gòu)造器叶沛、構(gòu)造器繼承等特性蒲讯。

Default Property Values ??

自定義初始化(Customizing Initialization)

可以通過(guò)輸入?yún)?shù)和可選類(lèi)型的屬性來(lái)自定義構(gòu)造過(guò)程,也可以在構(gòu)造過(guò)程中修改常量屬性灰署。

初始化參數(shù)(Initialization Parameters)

可以在定義構(gòu)造器的時(shí)候提供初始化參數(shù)判帮,語(yǔ)法和函數(shù)(方法)相同:


Initialization Parameters ??

參數(shù)名稱和標(biāo)簽(Parameter Names and Argument Labels)

和函數(shù)、方法的參數(shù)相同溉箕,構(gòu)造參數(shù)也有一個(gè)內(nèi)部名字和一個(gè)外部名字晦墙。

然而,構(gòu)造器不會(huì)像函數(shù)和方法一樣在括號(hào)前有一個(gè)可辨別的名字肴茄,因此在調(diào)用構(gòu)造器是晌畅,主要就是通過(guò)參數(shù)名字和類(lèi)型來(lái)確定應(yīng)該被調(diào)用的構(gòu)造器。所以參數(shù)很重要独郎,如果沒(méi)有提供參數(shù)的標(biāo)簽(外部名字)踩麦,Swift會(huì)為構(gòu)造器的每個(gè)參數(shù)自動(dòng)生成一個(gè)和內(nèi)部名字相同的外部名字:


Parameter Names and Argument Labels ??

無(wú)標(biāo)簽的構(gòu)造器參數(shù)(Initializer Parameters Without Argument Labels)

如果不希望為構(gòu)造器的某個(gè)參數(shù)提供外部名字枚赡,可以使用下劃線(_
)來(lái)顯式描述它的外部名氓癌,以此重寫(xiě)上面所說(shuō)的默認(rèn)行為:


Initializer Parameters Without Argument Labels ??

可選屬性類(lèi)型(Optional Property Types)

如果定制的類(lèi)型包含一個(gè)邏輯上允許取值為空的存儲(chǔ)型屬性——無(wú)論是因?yàn)樗鼰o(wú)法在初始化時(shí)賦值,還是因?yàn)樗谥竽硞€(gè)時(shí)間點(diǎn)可以賦值為空——都需要將它定義為可選類(lèi)型(optional type)贫橙√巴瘢可選類(lèi)型的屬性將自動(dòng)初始化為nil,表示這個(gè)屬性是有意在初始化時(shí)設(shè)置為空的:


Optional Property Types ??

構(gòu)造過(guò)程中常量屬性的修改(Assigning Constant Properties During Initialization)

可以在構(gòu)造過(guò)程中的任意時(shí)間點(diǎn)給常量屬性指定一個(gè)值卢肃,只要在構(gòu)造過(guò)程結(jié)束時(shí)是一個(gè)確定的值疲迂。一旦常量屬性被賦值,它將永遠(yuǎn)不可更改莫湘。

注意
對(duì)于類(lèi)的實(shí)例尤蒿,它的常量屬性只能在定義它的類(lèi)的構(gòu)造過(guò)程中修改,不能在子類(lèi)中修改幅垮。

Assigning Constant Properties During Initialization ??

默認(rèn)構(gòu)造器(Default Initializers)

如果結(jié)構(gòu)體或類(lèi)的所有屬性都有默認(rèn)值腰池,同時(shí)沒(méi)有自定義的構(gòu)造器,那么 Swift 會(huì)給這些結(jié)構(gòu)體或類(lèi)提供一個(gè)默認(rèn)構(gòu)造器(default initializers)忙芒。這個(gè)默認(rèn)構(gòu)造器將簡(jiǎn)單地創(chuàng)建一個(gè)所有屬性值都設(shè)置為默認(rèn)值的實(shí)例:


Default Initializers ??

結(jié)構(gòu)體類(lèi)型的逐一構(gòu)造器(Memberwise Initializers for Structure Types)

如果結(jié)構(gòu)體沒(méi)有提供自定義的構(gòu)造器示弓,它們將自動(dòng)獲得一個(gè)逐一成員構(gòu)造器,即使結(jié)構(gòu)體的存儲(chǔ)型屬性沒(méi)有默認(rèn)值呵萨。

逐一成員構(gòu)造器是用來(lái)初始化結(jié)構(gòu)體新實(shí)例里成員屬性的快捷方法奏属。在調(diào)用逐一成員構(gòu)造器時(shí),通過(guò)與成員屬性名相同的參數(shù)名進(jìn)行傳值來(lái)完成對(duì)成員屬性的初始賦值潮峦。

Memberwise Initializers for Structure Types ??

值類(lèi)型的構(gòu)造器代理(Initializer Delegation for Value Types)

構(gòu)造器可以通過(guò)其它構(gòu)造器來(lái)完成實(shí)例的部分構(gòu)造過(guò)程囱皿。這個(gè)過(guò)程就稱為構(gòu)造器代理勇婴,它能減少多個(gè)構(gòu)造器間的代碼重復(fù)。

構(gòu)造器代理的實(shí)現(xiàn)規(guī)則和形式在值類(lèi)型和類(lèi)類(lèi)型中有所不同嘱腥。值類(lèi)型(結(jié)構(gòu)體咆耿、枚舉)不支持繼承,所以構(gòu)造器代理的過(guò)程相對(duì)簡(jiǎn)單爹橱,因?yàn)樗鼈冎荒艽斫o自己的其它構(gòu)造器萨螺。
類(lèi)不一樣,它可以繼承自其它類(lèi)愧驱,這意味著類(lèi)有責(zé)任保證其所有繼承的存儲(chǔ)型屬性在構(gòu)造時(shí)也能正確的初始化慰技。

對(duì)于值類(lèi)型,使用 self.init 在自定義的構(gòu)造器中引用相同類(lèi)型中的其它構(gòu)造器组砚。并且只能在構(gòu)造器里調(diào)用 self.init吻商。

如果為某個(gè)值類(lèi)型定義一個(gè)自定義的構(gòu)造器,將無(wú)法訪問(wèn)到默認(rèn)構(gòu)造器(如果是結(jié)構(gòu)體糟红,還將無(wú)法訪問(wèn)逐一成員構(gòu)造器)艾帐。這種限制可以防止你為值類(lèi)型增加一個(gè)額外的且十分復(fù)雜的構(gòu)造器之后,仍然有人錯(cuò)誤的使用自動(dòng)生成的構(gòu)造器盆偿。

注意
但是如果希望默認(rèn)構(gòu)造器柒爸、逐一成員構(gòu)造器以及自己的自定義構(gòu)造器都能用來(lái)創(chuàng)建實(shí)例,可以將自定義的構(gòu)造器寫(xiě)到擴(kuò)展 (extension) 中事扭,而不是寫(xiě)在值類(lèi)型的原始定義中捎稚。

Memberwise Initializers for Structure Types ??

類(lèi)的繼承和初始化(Class Inheritance and Initialization)

類(lèi)里面的所有存儲(chǔ)型屬性,包括所有繼承自父類(lèi)的屬性求橄,都必須在構(gòu)造過(guò)程中設(shè)置初始值今野。

Swift 為類(lèi)類(lèi)型提供了兩種類(lèi)型的構(gòu)造器來(lái)確保實(shí)例中所有存儲(chǔ)型屬性都能獲得初始值,它們分別是指定構(gòu)造器和便利構(gòu)造器罐农。

指定構(gòu)造器和便利構(gòu)造器(Designated Initializers and Convenience Initializers)

指定構(gòu)造器是類(lèi)中最主要的構(gòu)造器条霜。一個(gè)指定構(gòu)造器將初始化類(lèi)中提供的所有屬性,并根據(jù)父類(lèi)鏈往上調(diào)用父類(lèi)的構(gòu)造器來(lái)實(shí)現(xiàn)父類(lèi)的初始化涵亏。

類(lèi)往往有很少的指定構(gòu)造器宰睡,但是通常一個(gè)類(lèi)只有一個(gè)。指定初始化是通過(guò) “funnel” 點(diǎn)初始化,并通過(guò)初始化過(guò)程持續(xù)進(jìn)行了父類(lèi)鏈溯乒。

每一個(gè)類(lèi)都必須擁有至少一個(gè)指定構(gòu)造器夹厌。在某些情況下,許多類(lèi)通過(guò)繼承了父類(lèi)中的指定構(gòu)造而滿足了這個(gè)條件裆悄。

便利構(gòu)造器是類(lèi)中比較次要的矛纹、輔助型的構(gòu)造器」饧冢可以定義便利構(gòu)造器來(lái)調(diào)用同一個(gè)類(lèi)中的指定構(gòu)造器,并為其參數(shù)提供默認(rèn)值。也可以定義便利構(gòu)造器來(lái)創(chuàng)建一個(gè)特殊用途或特定輸入值的實(shí)例璃哟。

當(dāng)只在必要的時(shí)候?yàn)轭?lèi)提供便利構(gòu)造器,比如說(shuō)某種情況下通過(guò)使用便利構(gòu)造器來(lái)快捷調(diào)用某個(gè)指定構(gòu)造器肄方,能夠節(jié)省更多開(kāi)發(fā)時(shí)間并讓類(lèi)的構(gòu)造過(guò)程更清晰明了。

指定構(gòu)造器和便利構(gòu)造器的語(yǔ)法(Syntax for Designated and Convenience Initializers)

類(lèi)的指定構(gòu)造器的寫(xiě)法跟值類(lèi)型簡(jiǎn)單構(gòu)造器一樣:

init(parameters) {
    // statements
}

便利構(gòu)造器也采用相同樣式的寫(xiě)法蹬癌,但需要在 init 關(guān)鍵字之前放置 convenience 關(guān)鍵字权她,并使用空格隔開(kāi):

convenience init(parameters) {
    statements
}

類(lèi)的構(gòu)造器代理規(guī)則(Initializer Delegation for Class Types)

為了簡(jiǎn)化指定構(gòu)造器和便利構(gòu)造器之間的調(diào)用關(guān)系,Swift 采用以下三條規(guī)則來(lái)限制構(gòu)造器之間的代理調(diào)用:

  1. 指定構(gòu)造器必須調(diào)用其直接父類(lèi)的指定構(gòu)造器逝薪。
  2. 便利構(gòu)造器必須調(diào)用同一類(lèi)中定義的其它構(gòu)造器隅要。
  3. 便利構(gòu)造器必須最終導(dǎo)致一個(gè)指定構(gòu)造器被調(diào)用。

這樣更好記:

  • 指定構(gòu)造器必須總是向上代理
  • 便利構(gòu)造器必須總是橫向代理

可以用一張圖來(lái)表示:


注意
這些規(guī)則不會(huì)影響類(lèi)的實(shí)例如何創(chuàng)建董济。任何上圖中戰(zhàn)士的構(gòu)造器都可以用來(lái)創(chuàng)建完全初始化的實(shí)例步清。這些規(guī)則只影響類(lèi)定義如何實(shí)現(xiàn)。

下圖中展示了一種涉及四個(gè)類(lèi)的更復(fù)雜的類(lèi)層級(jí)結(jié)構(gòu)虏肾。它演示了指定構(gòu)造器是如何在類(lèi)層級(jí)中充當(dāng)『管道』的作用廓啊,在類(lèi)的構(gòu)造器鏈上簡(jiǎn)化了類(lèi)之間的相互關(guān)系:


兩段式初始化(Two-Phase Initialization)

Swift 中類(lèi)的構(gòu)造過(guò)程包含兩個(gè)階段。在第一段封豪,每個(gè)存儲(chǔ)型屬性引入它們的類(lèi)指定一個(gè)初始值谴轮。當(dāng)每個(gè)存儲(chǔ)型屬性的初始值被確定后,第二個(gè)階段開(kāi)始撑毛,它會(huì)給每個(gè)類(lèi)一次機(jī)會(huì)书聚,在新實(shí)例準(zhǔn)備使用之前進(jìn)一步定制它們的存儲(chǔ)型屬性。

使用兩段式初始化會(huì)讓初始化安全藻雌,同時(shí)在整個(gè)類(lèi)層級(jí)結(jié)構(gòu)中給予了每個(gè)類(lèi)完全的靈活性。兩段式構(gòu)造過(guò)程可以防止屬性值在初始化之前被訪問(wèn)斩个,也可以防止屬性被另外一個(gè)構(gòu)造器意外的賦予不同的值胯杭。

注意
Swift 的兩段式初始化過(guò)程和 OC 的初始化類(lèi)似。最主要的區(qū)別在于階段 1受啥,OC 給每一個(gè)屬性賦值 0 或空值(比如說(shuō) 0 或 nil)做个。Swift 的初始化流程更加靈活,它允許設(shè)置定制的初始值滚局,并自如應(yīng)對(duì)某些屬性不能以 0 或 nil 作為合法默認(rèn)值的情況居暖。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市藤肢,隨后出現(xiàn)的幾起案子太闺,更是在濱河造成了極大的恐慌,老刑警劉巖嘁圈,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件省骂,死亡現(xiàn)場(chǎng)離奇詭異蟀淮,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)钞澳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)怠惶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人轧粟,你說(shuō)我怎么就攤上這事策治。” “怎么了兰吟?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵览妖,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我揽祥,道長(zhǎng)讽膏,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任拄丰,我火速辦了婚禮府树,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘料按。我一直安慰自己奄侠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布载矿。 她就那樣靜靜地躺著垄潮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闷盔。 梳的紋絲不亂的頭發(fā)上弯洗,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音逢勾,去河邊找鬼牡整。 笑死,一個(gè)胖子當(dāng)著我的面吹牛溺拱,可吹牛的內(nèi)容都是我干的逃贝。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼迫摔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沐扳!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起句占,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤沪摄,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體卓起,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡和敬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了戏阅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昼弟。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖奕筐,靈堂內(nèi)的尸體忽然破棺而出舱痘,到底是詐尸還是另有隱情,我是刑警寧澤离赫,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布芭逝,位于F島的核電站,受9級(jí)特大地震影響渊胸,放射性物質(zhì)發(fā)生泄漏旬盯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一翎猛、第九天 我趴在偏房一處隱蔽的房頂上張望胖翰。 院中可真熱鬧,春花似錦切厘、人聲如沸萨咳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)培他。三九已至,卻和暖如春遗座,著一層夾襖步出監(jiān)牢的瞬間舀凛,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工员萍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腾降,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓碎绎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親抗果。 傳聞我的和親對(duì)象是個(gè)殘疾皇子筋帖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

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

  • 官方文檔 初始化 Initialization是為準(zhǔn)備使用類(lèi),結(jié)構(gòu)體或者枚舉實(shí)例的一個(gè)過(guò)程冤馏。這個(gè)過(guò)程涉及了在實(shí)例里...
    hrscy閱讀 1,133評(píng)論 0 1
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,783評(píng)論 1 10
  • 構(gòu)造過(guò)程 構(gòu)造過(guò)程是使用類(lèi)日麸、結(jié)構(gòu)體或枚舉類(lèi)型的實(shí)例之前的準(zhǔn)備過(guò)程。在新實(shí)例可用前必須執(zhí)行這個(gè)過(guò)程,具體操作包括設(shè)置...
    蠱毒_閱讀 723評(píng)論 0 2
  • 將昨日的黎明瞬間封存 但不是永遠(yuǎn)的黑暗 是相思的心還是傷心的淚 億萬(wàn)年的等待 或許只是為了把一種信念傳遞 是宇宙時(shí)...
    泰安左眼皮跳跳閱讀 229評(píng)論 0 6
  • 昨日微信問(wèn)好友:聽(tīng)說(shuō)你病了代箭,現(xiàn)在恢復(fù)如何墩划? 回答:明天開(kāi)始第三次化療 我:化療?我聽(tīng)說(shuō)是腸梗阻啊嗡综,怎么化療了乙帮? 心...
    吊腳樓姑娘閱讀 351評(píng)論 2 3