Swift之init構(gòu)造方法

構(gòu)造方法是一個類創(chuàng)建對象最先也是必須調(diào)用的方法,在Swift語言體系中,構(gòu)造方法與普通的方法分界十分嚴(yán)格,從格式寫法上就有不同,普通方法函數(shù)要以func聲明,構(gòu)造方法統(tǒng)一為init命名,不需要func關(guān)鍵字聲明。
接下來簡單介紹下swift中的構(gòu)造方法,積累和鞏固知識的同時希望也能幫助到大家,另外有什么不對的地方歡迎大家指正??。

Swift中構(gòu)造方法分類:

  • Designated構(gòu)造方法
  • Convenience構(gòu)造方法

1、Designated構(gòu)造方法
又稱指定構(gòu)造方法,此方法init前不需要加關(guān)鍵字,是類中的主要構(gòu)造器。它會將類中所有的屬性賦值初始化,并且一路往上調(diào)用類的父類的指定構(gòu)造方法去初始化它們各自引入的屬性。每個類都必須至少有一個designated構(gòu)造方法,但是有些情況你會看到類中沒有聲明designated構(gòu)造方法,那是因為如果是一個子類,不寫任designated構(gòu)造方法,將會自動繼承父類所有designated構(gòu)造方法。另外,不寫任何designated構(gòu)造方法,系統(tǒng)其實也會默認生成一個構(gòu)造方法 init() {} 。
例:

//指定構(gòu)造方法
init (param:String) {
    ... //此處為了直觀看我用...表示省略
} 

2、Convenience構(gòu)造方法
又稱便利構(gòu)造方法,此方法init前需要加convenience關(guān)鍵字,是類中的次要構(gòu)造器。它必須調(diào)用同一個類中的指定構(gòu)造方法或其他的便利構(gòu)造方法(最后還是調(diào)用指定構(gòu)造方法)。每個類可以不需要,也可以定義多個。
例:

//便利構(gòu)造方法
convenience init (param:String) {
  self.init(...)
  ...
} 

Swift中構(gòu)造方法遵循規(guī)則:

官方文檔中有如下描述:

  • 子類designated構(gòu)造方法中必須調(diào)用父類的designated構(gòu)造方法。

  • convenience構(gòu)造方法中必須調(diào)用當(dāng)前類的構(gòu)造方法。

  • convenience構(gòu)造方法歸根結(jié)底要調(diào)用到designated構(gòu)造方法。

201671180544418.jpg

例:

    //子類
    //自定義指定構(gòu)造方法
    init (paramA:String) {
        super.init()//需要調(diào)用父類的構(gòu)造方法
    }
    
    //自定義便利構(gòu)造方法
    convenience init(paramB:String,paramC:String) {
        self.init(paramA:"lala")//調(diào)用自己的指定構(gòu)造方法
    }
    
    //自定義便利構(gòu)造方法
    convenience init(paramD:String) {
        self.init(paramB:"lalala",paramC:"llalalal")//也可以調(diào)用自己的便利構(gòu)造方法(最后還是調(diào)用指定構(gòu)造方法)
    }

Swift中重寫構(gòu)造方法:

  • 重寫父類的designated構(gòu)造方法,方法名前需要加override ,然后調(diào)用父類的(super.)designated構(gòu)造方法。
  • 重寫父類的convenience構(gòu)造方法,方法名前不需要加override,一種情況不加convenice關(guān)鍵字,需調(diào)用父類的(super.)designated構(gòu)造方法,另外一種情況加convenice關(guān)鍵字,則必須調(diào)用自己的(self.)構(gòu)造方法。
  • 父類中若帶有required關(guān)鍵字的構(gòu)造方法,子類只要有重寫或調(diào)用父類(super.)的designated構(gòu)造方法的,都需要對父類加有required關(guān)鍵字的方法也重寫實現(xiàn)(required關(guān)鍵字,強制子類實現(xiàn)某些構(gòu)造方法)

(注:convenience構(gòu)造方法是不能從子類中以 super 的方式被調(diào)用的)

Swift中構(gòu)造方法繼承的條件:

在 Swift 中,子類默認不會繼承父類的構(gòu)造方法,然而,如果某種條件滿足的話,父類的構(gòu)造方法還是可以繼承給子類。在通常情況下,這意味著你不必復(fù)寫父類的構(gòu)造方法,在安全的前提下可以以最低的代價繼承父類的構(gòu)造方法。
假設(shè)子類新增的屬性都提供了默認值,那么提供了以下兩條規(guī)則:

  • 規(guī)則1:
    如果你的子類沒有定義任何的指定構(gòu)造方法(新增便利構(gòu)造方法可有可無),那么子類會自動繼承父類的所有指定構(gòu)造方法。
  • 規(guī)則2:
    如果子類通過規(guī)則1,或者通過自定義實現(xiàn)父類的所有指定構(gòu)造方法,那么子類自動繼承父類的所有便利構(gòu)造方法。(子類以便利構(gòu)造方法覆蓋父類的指定構(gòu)造方法也視為對父類的指定構(gòu)造方法的實現(xiàn)。)

Swift中初始化的過程:

在 Swift 中,類的初始化需要經(jīng)歷兩個步驟,第一個步驟中,每一個該類引入的儲存屬性都需要給賦上一個初始值。完成后,執(zhí)行第二個步驟,每個類都可以再對屬性進行自定義修改。

  • 步驟1:
  1. 一個類的指定或便利初始化器需被調(diào)用
  2. 類的實例的內(nèi)存被申請,但還沒有初始化
  3. 指定初始化器確保當(dāng)前類引入的所有成員屬性都初始化,變量沒給賦值默認nil,常量若沒給賦值,須先賦值,注意要在該指定構(gòu)造器方法調(diào)用父類構(gòu)造(super.init(...))方法前賦值。 另注意:父類的成員屬性也會被子類繼承,如果要在子類復(fù)寫的父類方法中對繼承來的父類成員屬性進行重新構(gòu)造或賦值,則必須在調(diào)用父類構(gòu)造方法之后。步驟2的環(huán)節(jié)了
  4. 指定初始化器調(diào)用其父類的指定初始化器,繼續(xù)讓父類去初始化它所引入的成員屬性
  5. 上面這個過程一直進行直到最終的根類的指定初始化器被調(diào)用
  6. 當(dāng)根類的指定初始化器調(diào)用后,該類的實例就已經(jīng)確保了所有成員性都已經(jīng)初始化完成,步驟一完成。
  • 步驟2:
  1. 步驟二是從根類的指定初始化器開始一直向下,一層層到最終的子類的指定初始化器
  2. 在這個步驟中,每個類都有機會對已經(jīng)步驟一中初始化完成的實例再次進行自定義修改。此時初始化器已經(jīng)可以訪問 self,修改屬性或者調(diào)用實例方法了。

(注:遍歷構(gòu)造方法必須在調(diào)用同一個類中的指定構(gòu)造方法或其他的便利構(gòu)造方法(最后還是調(diào)用指定構(gòu)造方法),然后再為屬性賦值)

例:

class FatherClass {
        //父類的屬性
        var descF = "FatherClass"
        let ageF: Int
        init(age: Int) {
            ageF = age
        }
}
class ChildClass: FatherClass {
        //子類的屬性
        var descC = "ChildClass"
        let ageC: Int
        let sexC: String
        override init(age: Int) {
            //調(diào)用父類構(gòu)造方法前進行自己屬性的初始化賦值
            sexC = "男"
            ageC = age //在指定 init 里我們可以對 let 的實例常量進行賦值,這是初始化方法的重要特點。正常情況下 let 聲明的值是不可變的,無法被賦值,這對構(gòu)建線程安全的 API十分有用。而 init 只可能被調(diào)用一次,所以在 init 里我們可以為不變量進行賦值,而不會引起任何線程安全的問題  
            super.init(age: age + 30)
            //在調(diào)用父類構(gòu)造方法之后,可以對從父類繼承來的變量屬性進行重構(gòu)造
            descF = "ChildClassAndFatherClass"
        }

        //自定義遍歷構(gòu)造方法
        convenience init(name:String,age:Int) {
            self.init(age:5)
            //調(diào)用自己的指定構(gòu)造方法后才可為屬性賦值
            descC = "啦啦啦啦"
            descF = "lallal"
        }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 本章將會介紹 存儲屬性的初始賦值自定義構(gòu)造過程默認構(gòu)造器值類型的構(gòu)造器代理類的繼承和構(gòu)造過程可失敗構(gòu)造器必要構(gòu)造器...
    寒橋閱讀 837評論 0 0
  • 構(gòu)造過程 構(gòu)造過程是使用類、結(jié)構(gòu)體或枚舉類型的實例之前的準(zhǔn)備過程。在新實例可用前必須執(zhí)行這個過程,具體操作包括設(shè)置...
    蠱毒_閱讀 780評論 0 2
  • 20- 枚舉,枚舉原始值,枚舉相關(guān)值,switch提取枚舉關(guān)聯(lián)值 Swift枚舉: Swift中的枚舉比OC中的枚...
    iOS_恒仔閱讀 2,423評論 1 6
  • 基于數(shù)據(jù)的決策 一、概念:首先,數(shù)據(jù)是信息的載體,是這個世界的底牌,對數(shù)據(jù)的分析掌握可以大大提高決策質(zhì)量。 二、運...
    Sunflower1992閱讀 736評論 0 0
  • 每天都是幸福滿滿的樸太夫夫 “哥啊,想喝水~”因著地暖還沒修好,李太永吃完早飯就躲回了床上,懶洋洋的使喚著他哥。 ...
    甜奎奶八閱讀 325評論 0 2

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