Swift語(yǔ)法--初始化、反初始化

初始化

目的是確保第一次使用之前某類(lèi)型的新實(shí)例能夠正確初始化

為存儲(chǔ)屬性設(shè)置初始化值

類(lèi)或者結(jié)構(gòu)體實(shí)例化時(shí)必須為所有的存儲(chǔ)屬性設(shè)置一個(gè)合適的初始值??梢栽诔跏蓟骼餅榇鎯?chǔ)屬性設(shè)置一個(gè)初始值,也可以通過(guò)分配一個(gè)默認(rèn)的屬性值作為屬性定義的一部分

當(dāng)給一個(gè)存儲(chǔ)屬性分配默認(rèn)值或者在初始化器里設(shè)置它的值時(shí),不會(huì)調(diào)用任何屬性監(jiān)視器

初始化器

默認(rèn)的屬性值

可以指定默認(rèn)屬性值作為屬性聲明的一部分。

如果一個(gè)屬性一直保持相同的初始值,推薦使用默認(rèn)值而不是在初始化器里設(shè)置它

自定義初始化

初始化形式參數(shù)

與函數(shù)形式參數(shù)語(yǔ)法相同

形式參數(shù)名和實(shí)際參數(shù)標(biāo)簽

與函數(shù)一樣,但是由于初始化器的函數(shù)名是固定的,所以為了能夠區(qū)分,在沒(méi)有提供外部名的情況下Swift自動(dòng)為每一個(gè)形式參數(shù)提供一個(gè)外部名稱

無(wú)實(shí)際參數(shù)標(biāo)簽的初始化器形式參數(shù)

如果不想為初始化器形式參數(shù)使用實(shí)際參數(shù)標(biāo)簽,可以寫(xiě)一個(gè)下劃線替代明確的實(shí)際參數(shù)標(biāo)簽以重寫(xiě)默認(rèn)行為

可選屬性類(lèi)型

可選屬性在初始化時(shí)可以不提供值,自動(dòng)初始化為nil

在初始化中分配常量屬性

初始化的任意時(shí)刻,都可以給常量屬性賦值

對(duì)于類(lèi)實(shí)例,常量屬性在初始化中只能通過(guò)引用的類(lèi)修改,不能在子類(lèi)中被修改

默認(rèn)初始化器

如果沒(méi)有定義初始化器,Swift提供一個(gè)默認(rèn)初始化器,為所有的屬性提供默認(rèn)值

只有在給每個(gè)屬性提供默認(rèn)值的時(shí)候才能提供默認(rèn)初始化器,否則無(wú)法生成默認(rèn)初始化器

結(jié)構(gòu)體類(lèi)型的成員初始化器

如果結(jié)構(gòu)體類(lèi)型中沒(méi)有定義任何初始化器,它會(huì)自動(dòng)獲得一個(gè)成員初始化器。不同于默認(rèn)初始化器,結(jié)構(gòu)體會(huì)接收成員初始化器即使它的屬性沒(méi)有默認(rèn)值

值類(lèi)型的初始化器委托

初始化器可以調(diào)用其他初始化器來(lái)執(zhí)行部分實(shí)例的初始化。這個(gè)過(guò)程,就是所謂的初始化器委托,避免了多個(gè)初始化器里冗余代碼。

初始化器委托的運(yùn)作,以及允許哪些形式的委托,這些規(guī)則對(duì)于值類(lèi)型和類(lèi)類(lèi)型是不同的。原因在于值類(lèi)型不支持繼承,所以簡(jiǎn)單一些

如果你為值類(lèi)型定義了自定義初始化器,那么就不能訪問(wèn)那個(gè)類(lèi)型的默認(rèn)初始化器。這個(gè)限制防止別人意外的使用自動(dòng)初始化器而把復(fù)雜初始化器里提供的額外必要配置給覆蓋掉的情況發(fā)生。

如果想要自定義值類(lèi)型能夠使用默認(rèn)初始化器和成員初始化器初始化,以及自定義初始化器來(lái)初始化,把自定義初始化器寫(xiě)在擴(kuò)展里而不是作為值類(lèi)型原始定義的一部分可以實(shí)現(xiàn)。

類(lèi)的繼承和初始化

所有類(lèi)的存儲(chǔ)屬性,包括繼承而來(lái)的,都必須在初始化期間分配初始值

指定初始化器和便捷初始化器

指定初始化器是類(lèi)的主要初始化器。指定初始化器可以初始化所有那個(gè)類(lèi)引用的屬性并且調(diào)用合適的父類(lèi)初始化器來(lái)繼續(xù)這個(gè)初始化過(guò)程給父類(lèi)鏈。

類(lèi)偏向于少量指定初始化器,但至少得有一個(gè)。在某些情況下,這些需求可以通過(guò)從父類(lèi)繼承一個(gè)或者多個(gè)指定初始化器來(lái)滿足。

便捷初始化器是次要的??梢圆惶峁?。

指定初始化器和便捷初始化器語(yǔ)法

convenience
指定初始化器不需要修飾

類(lèi)類(lèi)型的初始化器委托

為了簡(jiǎn)化指定和便捷初始化器之間的調(diào)用關(guān)系,Swift指定三個(gè)規(guī)則

  1. 指定初始化器必須從他的直系父類(lèi)調(diào)用指定初始化器(繼承來(lái)的也算)
  1. 便捷初始化器必須從相同的類(lèi)里調(diào)用另一個(gè)初始化器
  2. 便捷初始化器最終必須調(diào)用一個(gè)指定初始化器

簡(jiǎn)單講,指定初始化器總是向上委托,便利初始化器從事橫向委托

兩段式初始化

在第一個(gè)階段,每一個(gè)存儲(chǔ)屬性被引入類(lèi)時(shí)分配了一個(gè)初始值,一旦每個(gè)存儲(chǔ)屬性的初始狀態(tài)被確定,第二個(gè)階段就開(kāi)始了,每個(gè)類(lèi)都有機(jī)會(huì)在新的實(shí)例準(zhǔn)備使用之前來(lái)定制它的存儲(chǔ)屬性

Swift編譯器執(zhí)行四種有效的安全檢查來(lái)確保兩段式初始化過(guò)程能夠順利完成:

  1. 指定初始化器必須保證在向上委托給父類(lèi)初始化器之前,其所在類(lèi)引入的所有屬性都要初始化完成
  1. 指定初始化器必須先向上委托父類(lèi)初始化器,然后才能為繼承的屬性設(shè)置新值。如果不這樣做,指定初始化器賦予的新值將被父類(lèi)中的初始化器所覆蓋
  2. 便捷初始化器必須先委托同類(lèi)中的其它初始化器,然后再為任意屬性賦新值(包括同類(lèi)里定義的屬性)。如果沒(méi)這么做,便捷初始化器賦予的新值將被自己類(lèi)中其它指定初始化器所覆蓋
  3. 初始化器在第一階段初始化完成之前,不能調(diào)用任何實(shí)例方法、不能讀取任何實(shí)例屬性的值,也不能引用self作為值

兩段初始化過(guò)程:

階段1

  1. 指定或便捷初始化器在類(lèi)中被調(diào)用
  2. 為這個(gè)類(lèi)的新實(shí)例分配內(nèi)存。內(nèi)存還沒(méi)有被初始化
  3. 這個(gè)類(lèi)的指定初始化器確保所有由此類(lèi)引入的存儲(chǔ)屬性都有一個(gè)值?,F(xiàn)在這些存儲(chǔ)屬性的內(nèi)存被初始化了
  4. 指定初始化器上交父類(lèi)的初始化器為其存儲(chǔ)屬性執(zhí)行相同的任務(wù)
  5. 這個(gè)調(diào)用父類(lèi)初始化器的過(guò)程將沿著初始化器鏈一直向上進(jìn)行,直到到達(dá)初始化器鏈的最頂部
  6. 一旦到達(dá)了初始化器的最頂部,在鏈頂部的類(lèi)確保左右的存儲(chǔ)屬性都有一個(gè)值,此實(shí)例的內(nèi)存被認(rèn)為完全初始化了,此時(shí)第一階段完成

階段2

  1. 從頂部初始化器往下,鏈中的每一個(gè)指定初始化器都有機(jī)會(huì)進(jìn)一步定制實(shí)例。初始化器現(xiàn)在能夠訪問(wèn)self并且可以修改它的屬性,調(diào)用它的實(shí)例方法等等
  2. 最終,鏈中任何便捷初始化器都有機(jī)會(huì)定制實(shí)例以及使用self

初始化器的繼承和重寫(xiě)

Swift的子類(lèi)不會(huì)默認(rèn)繼承父類(lèi)的初始化器。這種機(jī)制防止父類(lèi)的簡(jiǎn)單初始化器被一個(gè)更專(zhuān)用的子類(lèi)繼承并被用來(lái)創(chuàng)建一個(gè)沒(méi)有完全或錯(cuò)誤初始化的新實(shí)例的情況發(fā)生。

如果重寫(xiě)了一個(gè)匹配父類(lèi)便捷初始化器的子類(lèi)初始化器,父類(lèi)的便捷初始化器將永遠(yuǎn)不會(huì)通過(guò)你的子類(lèi)直接調(diào)用。因此,子類(lèi)(嚴(yán)格意義上來(lái)講)不能提供父類(lèi)便捷初始化器的重寫(xiě)。當(dāng)提供一個(gè)匹配父類(lèi)便捷初始化器的實(shí)現(xiàn)時(shí),不用寫(xiě)override

自動(dòng)初始化器的繼承

子類(lèi)默認(rèn)不會(huì)繼承父類(lèi)初始化器,但有例外

如果子類(lèi)引入的任何新屬性都提供了默認(rèn)值,則

  1. 子類(lèi)沒(méi)有定義任何指定初始化器,會(huì)自動(dòng)繼承父類(lèi)所有的指定初始化器
  2. 子類(lèi)提供了所有父類(lèi)指定初始化器的實(shí)現(xiàn):要么通過(guò)1中繼承而來(lái),要么全部自定義。它自動(dòng)繼承所有的父類(lèi)便捷初始化器

指定和便利初始化器的操作

可失敗初始化器

不能定義可失敗初始化器和非可失敗初始化器為相同的形式參數(shù)類(lèi)型和名稱

可失敗初始化器通過(guò)返回nil表明失敗

枚舉的可失敗初始化器

帶有原始值枚舉的可失敗初始化器

初始化失敗的傳遞

重寫(xiě)可失敗初始化器

可以重寫(xiě)父類(lèi)的可失敗初始化器,也可用子類(lèi)的非可失敗初始化器來(lái)重寫(xiě)父類(lèi)可失敗初始化器

可失敗初始化器init!

必要初始化器

required
子類(lèi)必須實(shí)現(xiàn)

通過(guò)閉包和函數(shù)來(lái)設(shè)置屬性的默認(rèn)值

可以使用閉包或者全局函數(shù)來(lái)為屬性提供默認(rèn)值,當(dāng)這個(gè)屬性初始化時(shí),閉包或者函數(shù)就會(huì)被調(diào)用

class SomeClass {
    let someProperty: SomeType = {
    // create a default value for someProperty inside this closure
    // someValue must be of the same type as SomeType
    return someValue
    }()
}

反初始化

反初始化器原理

反初始化器deinit后面不需要寫(xiě)圓括號(hào)

子類(lèi)的反初始化器調(diào)用結(jié)束之后父類(lèi)的反初始化器會(huì)被調(diào)用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 官方文檔 初始化 Initialization是為準(zhǔn)備使用類(lèi),結(jié)構(gòu)體或者枚舉實(shí)例的一個(gè)過(guò)程。這個(gè)過(guò)程涉及了在實(shí)例里...
    hrscy閱讀 1,201評(píng)論 0 1
  • 初始化 (Initialization) 自從蘋(píng)果2014年發(fā)布Swift,到現(xiàn)在已經(jīng)兩年多了,而Swift也來(lái)到...
    Lebron_James閱讀 1,269評(píng)論 0 0
  • 初始化(Initialization) 初始化是類(lèi)、結(jié)構(gòu)體、枚舉類(lèi)型的準(zhǔn)備過(guò)程。這個(gè)過(guò)程涉及到所有存儲(chǔ)屬性的初始化...
    泗哥閱讀 5,708評(píng)論 0 3
  • 本章將會(huì)介紹 存儲(chǔ)屬性的初始賦值自定義構(gòu)造過(guò)程默認(rèn)構(gòu)造器值類(lèi)型的構(gòu)造器代理類(lèi)的繼承和構(gòu)造過(guò)程可失敗構(gòu)造器必要構(gòu)造器...
    寒橋閱讀 839評(píng)論 0 0
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評(píng)論 19 139

友情鏈接更多精彩內(nèi)容