Swift構(gòu)造器總結(jié)(限制&注意點(diǎn))【轉(zhuǎn)】

原文:http://ghui.me/post/2016/05/swift-init/

Swift的構(gòu)造器的編寫規(guī)則要比其它語言麻煩很多, 有很多限制, 有些限制也不是那么容易想明白的, 但我想Swift的設(shè)計(jì)者肯定是有自己的考慮楔脯,不會(huì)平白無故的去設(shè)置這些限制汰规,在這篇文章中我將試著總結(jié)一下Swift語言在構(gòu)造過程中的種種限制以及為什么會(huì)需要這些限制.

1: Swift會(huì)為構(gòu)造器的每個(gè)參數(shù)自動(dòng)生成一個(gè)跟內(nèi)部名字相同的外部名

構(gòu)造器并不像函數(shù)和方法那樣在括號前有一個(gè)可辨別的名字(構(gòu)造器統(tǒng)一叫init), 為了提高構(gòu)造器的可讀性就有了這條限制, 當(dāng)然如果你實(shí)在是不想為構(gòu)造器提供外部名,可以使用下劃線_來顯式描述它的外部名, 這樣就不會(huì)有上述默認(rèn)行為了.

2: 任何一個(gè)構(gòu)造器都必須使當(dāng)前對象內(nèi)的非lazy非Optional類型的存儲(chǔ)屬性獲得確定值

如果你之前做過Java開發(fā), 你可能會(huì)對這一點(diǎn)產(chǎn)生疑惑, 在Java的構(gòu)造器里我們是不需要對所有的字段顯示進(jìn)行賦值的.
其實(shí)這個(gè)和Swift引入的Optional有關(guān),在Swift中非Optional的變量默認(rèn)是不會(huì)有值的, 除非你將它顯示的定義為Optional的, 換句話說Swift中Optional類型的變量才相當(dāng)于Java中的變量(java中的全局變量會(huì)自動(dòng)被賦予默認(rèn)值).而Swift中Optional類型的變量才會(huì)有默認(rèn)值nil, 而且構(gòu)造器的目的就是分配內(nèi)存以及使當(dāng)前對象處于一個(gè)確定的狀態(tài)(屬性都有值包括nil)

3: 如果結(jié)構(gòu)體或類的所有的屬性都有默認(rèn)值, Swift才會(huì)為它們提供默認(rèn)構(gòu)造器

在java中如果你沒有定義構(gòu)造器, Java就會(huì)自動(dòng)為你提供一個(gè)默認(rèn)構(gòu)造器, Swift為什么不?
基實(shí)這個(gè)和限制2的原因是一樣的, 首先構(gòu)造器要保證當(dāng)前對象所有的屬性都有值, 而Swift中的非Optionl類型的變量沒有默認(rèn)值, 所以只有當(dāng)所有屬性都有默認(rèn)值的情況下Swift才能提供默認(rèn)構(gòu)造器.

4: 如果你自定義了構(gòu)造器, 那么默認(rèn)構(gòu)造器會(huì)丟失(如果是結(jié)構(gòu)體苦囱,還將丟失逐一成員構(gòu)造器)

這種限制可以防止你為值類型增加了一個(gè)額外的且十分復(fù)雜的構(gòu)造器之后,仍然有人錯(cuò)誤的使用自動(dòng)生成的構(gòu)造器. 如果你想保留默認(rèn)構(gòu)造器逐一成員構(gòu)造器以及你自己定義的構(gòu)造器,你可以將自定義構(gòu)造器定義到extension中

5. 指定構(gòu)造器與便利構(gòu)造器是針對類而言的, 值類型的構(gòu)造器沒有這一說

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

之所以要這樣規(guī)定, 官方的說法是為了簡化指定構(gòu)造器與便利構(gòu)造器之間的調(diào)用關(guān)系:
1: 指定構(gòu)造器必須調(diào)用其直接父類的的指定構(gòu)造器
2: 便利構(gòu)造器必須調(diào)用同一類中定義的其它構(gòu)造器
3: 便利構(gòu)造器必須最終導(dǎo)致一個(gè)指定構(gòu)造器被調(diào)用


7. 兩段式構(gòu)造過程

第一個(gè)階段: 每個(gè)存儲(chǔ)屬性都獲得一個(gè)初始值
第二個(gè)階段: 進(jìn)一步定制存儲(chǔ)屬性的值
兩段式構(gòu)造過程可以防止屬性在初始化之前被訪問, 也可以防止屬性被另外一個(gè)構(gòu)造器意外地賦予不同的值.
這個(gè)怎么理解呢? 若屬性在初始化之前(第一階段結(jié)束之前)被訪問, 顯然這種情況是沒有意義的,因?yàn)檫@個(gè)時(shí)候?qū)傩赃€沒有任何值, 另外一種情況若當(dāng)前被訪問的屬性是從父類繼承過來的, 如果它在初始化之前被訪問,也是沒有意義的, 因?yàn)樗鼤?huì)被后面的super.init方法重新賦予初始值.

我對兩段式構(gòu)造過程的理解: 之所以要分兩段式來構(gòu)造和Swift引入Optional的概念還是分不開的, Swift中的變量默認(rèn)都不是Optional的, 這些變量不像其它語言(如Java)中的那樣會(huì)默認(rèn)有初始值, 所以必須需要第一階段來確定一個(gè)初始值.換個(gè)角度來看, 其它語言的構(gòu)造器相當(dāng)于直接是從第二個(gè)階段開始的, 它們的第一階段相當(dāng)于是在定義屬性時(shí)(這個(gè)時(shí)候系統(tǒng)會(huì)默認(rèn)分配一個(gè)默認(rèn)值, 如果你不顯式的賦予它初始值). 所以其實(shí),如果你在Swift中給你的屬性在定義時(shí)就顯式的賦予了初始值,或者你的屬性是Optional的, 那么你在寫構(gòu)造器時(shí)也就沒有這些限制了, 因?yàn)檫@個(gè)時(shí)候在init方法中你相當(dāng)于是直接從第二個(gè)階段開始的.

8. 4種安全檢查

指定構(gòu)造器必須保證它所在類引入的所有屬性都必須先初始化完成,之后才能將其它構(gòu)造任務(wù)向上代理給父類中的構(gòu)造器.
指定構(gòu)造器必須先向上代理調(diào)用父類構(gòu)造器吃靠,然后再為繼承的屬性設(shè)置新值弓乙。如果沒這么做塘砸,指定構(gòu)造器賦予的新值將被父類中的構(gòu)造器所覆蓋节仿。
便利構(gòu)造器必須先代理調(diào)用同一類中的其它構(gòu)造器,然后再為任意屬性賦新值掉蔬。如果沒這么做廊宪,便利構(gòu)造器賦予的新值將被同一類中其它指定構(gòu)造器所覆蓋。
構(gòu)造器在第一階段構(gòu)造完成之前女轿,不能調(diào)用任何實(shí)例方法箭启,不能讀取任何實(shí)例屬性的值,不能引用self作為一個(gè)值蛉迹。
這4項(xiàng)中只有第一條比較難理解一些傅寡,當(dāng)初困擾了好久,后來在萬能的stackoverflow上找到的答案北救,詳情

9. Swift中的子類默認(rèn)不會(huì)繼承父類的構(gòu)造器

Swift的這種機(jī)制可以防止一個(gè)父類的簡單構(gòu)造器被一個(gè)更精細(xì)的子類繼承荐操,并被錯(cuò)誤地用來創(chuàng)建子類的實(shí)例。父類的構(gòu)造器僅會(huì)在安全和適當(dāng)?shù)那闆r下被繼承珍策。

10. 你只能重寫父類的指定構(gòu)造器, 無法重寫父類的便利構(gòu)造器

為了簡化構(gòu)造器之間的調(diào)用關(guān)系, 便利構(gòu)造器必須總是橫向代理. 也就是說在便利構(gòu)造器中是無法訪問父類的構(gòu)造器的, 也就不能完成從父類中繼承下來的屬性的初始化, 導(dǎo)致無法完成子類的完全初始化, 所以子類是不能重寫父類的便利構(gòu)造器的.

11. 子類不僅可以重寫父類的指定構(gòu)造器, 還可以將其重寫為便利構(gòu)造器

12. 構(gòu)造器的自動(dòng)繼承

若子類中引入的存儲(chǔ)屬性都有缺省值, 且子類中沒有定義任何構(gòu)造方法. 那么子類將會(huì)自動(dòng)繼承父類中所有的構(gòu)造方法(包括便利構(gòu)造方法)
若子類只是重寫了父類中的部分構(gòu)造方法, 則子類不再會(huì)自動(dòng)繼承父類中的其他構(gòu)造方法
若子類重寫了父類中的所有指定構(gòu)造方法, 則子類同時(shí)會(huì)自動(dòng)繼承父類中所有的便利構(gòu)造方法
我的理解: 父類的構(gòu)造器只會(huì)在安全和適當(dāng)?shù)那闆r下被繼承, 滿足上面三種條件中的任何一條, 子類去自動(dòng)繼承父類中的構(gòu)造方法都是適當(dāng)?shù)?不會(huì)引起任何構(gòu)造過程的混亂.

13. 可失敗構(gòu)造器的參數(shù)列表不能與其它非可失敗構(gòu)造器的參數(shù)列表相同

若參數(shù)列表相同, 則可以認(rèn)為兩個(gè)方法是同一個(gè)方法, 而一個(gè)方法不能同時(shí)是非可失敗與可失敗的

14. 可失敗構(gòu)造器,在返回nil前必須要將所有的stroed property賦值

從swift2.2開始已沒有此限制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淀零,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子膛壹,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件模聋,死亡現(xiàn)場離奇詭異肩民,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)链方,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門持痰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人祟蚀,你說我怎么就攤上這事工窍。” “怎么了前酿?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵患雏,是天一觀的道長。 經(jīng)常有香客問我罢维,道長淹仑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任肺孵,我火速辦了婚禮匀借,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘平窘。我一直安慰自己吓肋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布瑰艘。 她就那樣靜靜地躺著是鬼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪磅叛。 梳的紋絲不亂的頭發(fā)上屑咳,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機(jī)與錄音弊琴,去河邊找鬼兆龙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛敲董,可吹牛的內(nèi)容都是我干的紫皇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼腋寨,長吁一口氣:“原來是場噩夢啊……” “哼聪铺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起萄窜,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤铃剔,失蹤者是張志新(化名)和其女友劉穎撒桨,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體键兜,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡凤类,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了普气。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谜疤。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖现诀,靈堂內(nèi)的尸體忽然破棺而出夷磕,到底是詐尸還是另有隱情,我是刑警寧澤仔沿,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布坐桩,位于F島的核電站,受9級特大地震影響于未,放射性物質(zhì)發(fā)生泄漏撕攒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一烘浦、第九天 我趴在偏房一處隱蔽的房頂上張望抖坪。 院中可真熱鬧,春花似錦闷叉、人聲如沸擦俐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚯瞧。三九已至,卻和暖如春品擎,著一層夾襖步出監(jiān)牢的瞬間埋合,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工萄传, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甚颂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓秀菱,卻偏偏與公主長得像振诬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子衍菱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

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

  • 本章將會(huì)介紹 存儲(chǔ)屬性的初始賦值自定義構(gòu)造過程默認(rèn)構(gòu)造器值類型的構(gòu)造器代理類的繼承和構(gòu)造過程可失敗構(gòu)造器必要構(gòu)造器...
    寒橋閱讀 769評論 0 0
  • 構(gòu)造過程 構(gòu)造過程是使用類脊串、結(jié)構(gòu)體或枚舉類型的實(shí)例之前的準(zhǔn)備過程辫呻。在新實(shí)例可用前必須執(zhí)行這個(gè)過程清钥,具體操作包括設(shè)置...
    蠱毒_閱讀 724評論 0 2
  • 構(gòu)造過程是使用類、結(jié)構(gòu)體或枚舉類型的實(shí)例之前的準(zhǔn)備過程放闺。在新實(shí)例可用前必須執(zhí)行這個(gè)過程循捺,具體操作包括設(shè)置實(shí)例中每個(gè)...
    莽原奔馬668閱讀 682評論 0 3
  • 想要的得不到 得不到的最想要
    Fairy空心玻璃瓶閱讀 178評論 0 0
  • 現(xiàn)在起 我再也不想靠你什么
    DingH閱讀 180評論 0 0