Swift 中的指定構造器和便利構造器 [譯文]

此文章為本人翻譯的譯文,版權為原作者所有遗遵。
英文原文:Designated Initializers and Convenience Initializers in Swift

今天我們將了解有關類構造器的另一個部分蜻势,Swift 語言提供了兩個不同類型的構造器琅束,分別稱為指定構造器便利構造器愿题,他們其實已經存在于 Objective-C 中免胃,但到了 Swift 中它們有了點小變化,并且也引入了一個非常有用的關鍵字辣恋。下面我們將討論一下這個話題亮垫,看看它們如何結合起來使你的類更加好用。

指定構造器

像 Swift 中大部分的構造器伟骨,指定構造器的名字就非常恰當地解釋了它所做的工作饮潦。它們是一個類最主要的構造器。一個類必須有一個指定構造器底靠,但并不是說只能有一個害晦。如果必要特铝,你可以聲明多個暑中,但是通常情況一個就足夠了壹瘟。

下面我們來簡單看看指定構造器是什么樣子:

init(sender: String, recipient: String) {
    self.sender = sender
    self.recipient = recipient

    timeStamp = NSDate()
}

是不是看起來十分熟悉呢?我們之前有篇文章 Classes In Swift — An Introduction and Using a Nested Type in Swift (英文) 里介紹了一個 Message 類鳄逾,這就是創(chuàng)建它的一個指定構造器的語法稻轨。我們的這個類只有一個構造器,所以它必須是指定構造器雕凹。創(chuàng)建它你只需要用到 init 這個關鍵字殴俱,配合幾個需要用到的參數,就大功告成了枚抵。

便利構造器

便利構造器的作用也正如其名线欲,他們就是用來讓構造類的過程更簡單。如果說指定構造器需要把所有的屬性初始化好汽摹,并讓用戶自己傳遞這些屬性的值李丰,那便利構造器就是把其中幾個屬性硬編碼了,這樣我們就能用盡量少的參數去構造一個相同的對象了逼泣。通常趴泌,我們用便利構造器將對象用一些默認值進行初始化來讓它們適合某種使用場景。

上面的構造器也許應該是一個便利構造器拉庶,因為它設置了 timeStamp 屬性而沒有讓用戶指定任何值嗜憔。像我上面所說的,我認為指定構造器需要讓用戶傳遞所有需要設置的屬性值(除非有些屬性值是由其他參數值衍生計算而來的)氏仗。但這也只是個人偏好啦吉捶,上面那種寫法作為指定構造器也是完全合法的,畢竟我們說 timeStamp 就是 Message 對象被構造的時間嘛皆尔。

盡管如此帚稠,讓我們?yōu)槲覀兊念愄砑右粋€便利構造器,讓這個對象表示“它發(fā)送一個消息給它自己”床佳。在這種情況下滋早,我們就不需要傳遞兩個不同的參數了,因為發(fā)送者就是接受者砌们,所以我們聲明一個只接受一個參數的便利構造器:

convenience init(sender: String) {
    self.init(sender: sender, recipient: sender)
}

它們在語法上是不同的杆麸,便利構造器有個 convenience 關鍵字在 init 之前,其他方面到時非常相似浪感。因為我們只取了一個參數昔头,所以我們就把這一個參數分別傳遞給指定構造器的兩個參數。

兩種構造器的使用原則

Swift 有三個有關兩種構造器相互使用的原則影兽,這里我直接引用 Apple 的 iBook 原文揭斧,就不進行解釋了:

  1. 一個指定構造器必須調用它直系父類的一個指定構造器。
  2. 一個便利構造器必須調用這個類自身的另一個構造器。
  3. 一個便利構造器最終一定會調用一個指定構造器讹开。



    引用自:Apple Inc. “The Swift Programming Language” iBooks

所以你能看到我們的便利構造器滿足了上述的第 2 和 3 條原則盅视。我們的指定構造器也處在類層次的最頂端,因此我們不需要調用父類的構造器(以滿足第一天原則)旦万。如果你重新調用了它闹击,一定是它有一個子類,就像下面這個 TextMessage 類:

init(content: String, sender: String, recipient: String) {
    self.content = content
    super.init(sender: sender, recipient: recipient)
}

你看成艘,它滿足了第一條原則了赏半。我們首先設置了這個類自身的 content 屬性,然后調用了父類的指定構造器淆两,這就完成這個類的初始化了断箫。這也是和 Objective-C 的差異,我們在 Objective-C 中是先初始化父類秋冰,再設置自己的屬性瑰枫。當然,回到 Swift 中丹莲,如果需要你也可在調用完其父類后再設置繼承來的屬性光坝。

根據 WWDC 的一個視頻,這顯然取決于類繼承的工作方式甥材。舉個例子盯另,如果一個父類調用了一個子類復寫的方法,父類實際上將會調用子類復寫后的方法實現(xiàn)(因為已經被復寫了嘛)洲赵,如果我們沒有完全初始化好我們子類的屬性鸳惯,并且復寫方法依賴于他們,那我們就遇到麻煩了叠萍。

這些原則有一些細微差別芝发。在第二條原則中,一個便利構造器必須調用另一個構造器苛谷,其實不必是指定構造器辅鲸,隨便一個構造器都可以。如果你需要腹殿,你可以聲明幾個便利構造器独悴,然后相互調用,這種鏈式調用時沒問題的锣尉。但最終還是要符合第三條原則就對了刻炒。

舉個例子吧:

convenience init() {
    self.init(content: "")
}

convenience init(content: String) {
    self.init(content: content, sender: "Myself")
}

convenience init(content: String, sender: String) {
    self.init(content: content, sender: sender, recipient: sender)
}

你能看到無參便利構造器傳遞了一個默認參數調用了另外一個便利構造器,另一個又是如此自沧,但最終指定構造器還是被調用了坟奥。

我們之前聲明的便利構造器設置了相同的 senderrecipient 來達到某些目的,為什么不子類化一個新類來解決這個問題呢?那么...

class NoteMessage: Message {
    let content: String

    init(content: String, theUser: String) {
        self.content = content
        super.init(sender: theUser)
    }

額爱谁,看來我們想當然了晒喷,別忘了第一條原則,一個指定構造器必須直接調用其直系父類的指定構造器管行。但我們嘗試去調用它的一個便利構造器了厨埋,這看來是不行的邪媳。

我不知道為什么 Swift 設計成這樣捐顷,畢竟一個便利構造器最終都會調用一個指定構造器。也許這迫使我們去思考最合適的默認屬性值雨效,而不是只顧便利迅涮。又或許以后這點會改變?誰知道呢徽龟。

總結 (譯者按)

老外寫文章有點啰嗦了叮姑,我這里也就不總結了,如果你認真閱讀了本文据悔,我相信你對指定構造器便利構造器一定有了很清晰的認識传透。總的來說就是极颓,便利構造器是為你類的初始化工作提供方便的朱盐,它們最終一定要依賴于那些真正使你類能正常工作的初始化工作,這也就是指定構造器的工作菠隆。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末兵琳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子骇径,更是在濱河造成了極大的恐慌躯肌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件破衔,死亡現(xiàn)場離奇詭異清女,居然都是意外死亡,警方通過查閱死者的電腦和手機晰筛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門校仑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人传惠,你說我怎么就攤上這事迄沫。” “怎么了卦方?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵羊瘩,是天一觀的道長。 經常有香客問我,道長尘吗,這世上最難降的妖魔是什么逝她? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮睬捶,結果婚禮上黔宛,老公的妹妹穿的比我還像新娘。我一直安慰自己擒贸,他們只是感情好臀晃,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著介劫,像睡著了一般徽惋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上座韵,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天险绘,我揣著相機與錄音,去河邊找鬼誉碴。 笑死宦棺,一個胖子當著我的面吹牛,可吹牛的內容都是我干的黔帕。 我是一名探鬼主播代咸,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蹬屹!你這毒婦竟也來了侣背?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤慨默,失蹤者是張志新(化名)和其女友劉穎贩耐,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體厦取,經...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡潮太,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了虾攻。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铡买。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖霎箍,靈堂內的尸體忽然破棺而出奇钞,到底是詐尸還是另有隱情,我是刑警寧澤漂坏,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布景埃,位于F島的核電站媒至,受9級特大地震影響,放射性物質發(fā)生泄漏谷徙。R本人自食惡果不足惜拒啰,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望完慧。 院中可真熱鬧谋旦,春花似錦、人聲如沸屈尼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸿染。三九已至指蚜,卻和暖如春乞巧,著一層夾襖步出監(jiān)牢的瞬間涨椒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工绽媒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蚕冬,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓是辕,卻偏偏與公主長得像囤热,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子获三,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內容

  • 本章將會介紹 存儲屬性的初始賦值自定義構造過程默認構造器值類型的構造器代理類的繼承和構造過程可失敗構造器必要構造器...
    寒橋閱讀 767評論 0 0
  • 構造過程是使用類疙教、結構體或枚舉類型的實例之前的準備過程棺聊。在新實例可用前必須執(zhí)行這個過程,具體操作包括設置實例中每個...
    莽原奔馬668閱讀 680評論 0 3
  • 構造過程 構造過程是使用類贞谓、結構體或枚舉類型的實例之前的準備過程限佩。在新實例可用前必須執(zhí)行這個過程,具體操作包括設置...
    蠱毒_閱讀 723評論 0 2
  • 123.繼承 一個類可以從另外一個類繼承方法,屬性和其他特征裸弦。當一個類繼承另外一個類時, 繼承類叫子類, 被繼承的...
    無灃閱讀 1,380評論 2 4
  • 午休過后是體育課祟同,有些時候就是緣分來了擋也擋不住呀!高一B班——也就是齊月木他們班的體育課正好和程吏宇他們班的體育...
    見曦焉閱讀 740評論 0 0