Swift 結(jié)構(gòu)體構(gòu)造器

  • Swift 中的結(jié)構(gòu)體和類跟其它面向?qū)ο笳Z言一樣都有構(gòu)造函數(shù), 而OC是沒有的
  • Swift 要求實(shí)例化一個(gè)結(jié)構(gòu)體或類的時(shí)候, 所有的成員變量都必須有初始值
  • 構(gòu)造函數(shù)的意義就是用于初始化所有成員變量的, 而不是分配內(nèi)存, 分配內(nèi)存是系統(tǒng)幫我們做的.
  • 如果結(jié)構(gòu)體中的所有屬性都有默認(rèn)值, 可以調(diào)用 ()構(gòu)造一個(gè)結(jié)構(gòu)體實(shí)例如果結(jié)構(gòu)體中的屬性沒有默認(rèn)值, 可以自定義構(gòu)造器, 并在構(gòu)造器中給所有的屬性賦值

在Swift中,定義為結(jié)構(gòu)體的類型會自動獲得由編譯器生成的默認(rèn)初始化程序——所謂的“成員構(gòu)造器”,因?yàn)榫幾g器將根據(jù)給定結(jié)構(gòu)體的成員(即其存儲的屬性)生成該初始化程序。

例如,如果我們定義了一個(gè)User具有nameage屬性的結(jié)構(gòu)體,則可以使用其成員構(gòu)造器來簡單地通過傳遞這兩個(gè)屬性的值來創(chuàng)建實(shí)例:

struct User {
    var name: String
    var age: Int
}

let user = User(name: "韋弦", age: 9)

另一方面,當(dāng)編譯器合成成員構(gòu)造器時(shí),將完全忽略計(jì)算屬性——因此,即使我們添加一個(gè)成員屬性,我們?nèi)匀豢梢韵褚郧耙粯永^續(xù)使用上述初始化程序:

struct User {
    var name: String
    var age: Int
    var isAdult: Bool { age >= 18 }
}

let user = User(name: "韋弦", age: 9)

從 Swift 5.1 開始,成員構(gòu)造器也考慮了默認(rèn)屬性值——這意味著,如果我們?yōu)?code>age屬性提供默認(rèn)值,則User只需傳遞一個(gè)name即可創(chuàng)建實(shí)例:

struct User {
    var name: String
    var age: Int = 18
    var isAdult: Bool { age >= 18 }
}

// 有如下兩種初始化方式
let user1 = User(name: "zhy")
let user2 = User(name: "韋弦", age: 9)

如果該類型具有private私有屬性,只要這些屬性具有默認(rèn)值,我們還是可以正常使用其成員構(gòu)造器,和上面沒有差異,但是如果私有屬性沒有默認(rèn)值,則必須手動編寫該類型的構(gòu)造器——以便能夠從外部傳入值為該屬性賦值:

struct User {
    var name: String
    private var age: Int
    var isAdult: Bool { age >= 18 }

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

let user = User(name: "韋弦", age: 9)

不過,要記住的一件事是,成員構(gòu)造器永遠(yuǎn)不會具有高于internal的訪問級別,這意味著我們只能在定義其類型的模塊內(nèi)部使用它們。

最初,這似乎是一個(gè)奇怪的限制,但它確實(shí)有其優(yōu)點(diǎn),因?yàn)槲覀兛梢哉f應(yīng)該始終設(shè)計(jì)供公眾使用的顯式API,而不必將它們與數(shù)據(jù)的內(nèi)部結(jié)構(gòu)聯(lián)系在一起。

因此,總而言之,在以下情況下,我們可以使用結(jié)構(gòu)體默認(rèn)生成的成員構(gòu)造器:

  • 它的所有成員都是可見的或具有默認(rèn)值。
  • 我們正在與定義該結(jié)構(gòu)體的模塊相同的模塊中創(chuàng)建一個(gè)實(shí)例。

所有其他情況都要求我們至少到目前為止至少手動實(shí)現(xiàn)一個(gè)初始化程序。

當(dāng)我們?yōu)榻Y(jié)構(gòu)體創(chuàng)建便利構(gòu)造器的時(shí)候,我們可以在 擴(kuò)展extension 中聲明該便利構(gòu)造器,這樣做的好處是,當(dāng)我們定義一些便利構(gòu)造器方便初始化的同時(shí),不會覆蓋編譯器生成的成員構(gòu)造器:

struct User {
    var name: String
    var gender: Gender
    var age: Int
    var isAdult: Bool { age >= 18 }

    enum Gender {
        case man,woman,other
    }
}


extension User {
    init(name: String, age: Int) {
        self.init(name: name, gender: .man, age: 18)
    }
}

// 可以有如下兩種初始化方法
let user1 = User(name: "韋弦", age: 9)
let user2 = User(name: "zhy", gender: .man, age: 18)

如果直接寫在結(jié)構(gòu)體內(nèi),則初始化 user2代碼會報(bào)錯(cuò),只剩下新聲明的便利構(gòu)造器。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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