- Swift 中的結(jié)構(gòu)體和類跟其它面向?qū)ο笳Z言一樣都有構(gòu)造函數(shù), 而OC是沒有的
- Swift 要求實例化一個結(jié)構(gòu)體或類的時候, 所有的成員變量都必須有初始值
- 構(gòu)造函數(shù)的意義就是用于初始化所有成員變量的, 而不是分配內(nèi)存, 分配內(nèi)存是系統(tǒng)幫我們做的.
- 如果結(jié)構(gòu)體中的所有屬性都有默認(rèn)值, 可以調(diào)用
()
構(gòu)造一個結(jié)構(gòu)體實例如果結(jié)構(gòu)體中的屬性沒有默認(rèn)值, 可以自定義構(gòu)造器, 并在構(gòu)造器中給所有的屬性賦值
在Swift中,定義為結(jié)構(gòu)體的類型會自動獲得由編譯器生成的默認(rèn)初始化程序——所謂的“成員構(gòu)造器”结借,因為編譯器將根據(jù)給定結(jié)構(gòu)體的成員(即其存儲的屬性)生成該初始化程序硬毕。
例如,如果我們定義了一個User
具有name
和age
屬性的結(jié)構(gòu)體辫继,則可以使用其成員構(gòu)造器來簡單地通過傳遞這兩個屬性的值來創(chuàng)建實例:
struct User {
var name: String
var age: Int
}
let user = User(name: "韋弦", age: 9)
另一方面,當(dāng)編譯器合成成員構(gòu)造器時,將完全忽略計算屬性——因此喻圃,即使我們添加一個成員屬性蒋纬,我們?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
只需傳遞一個name
即可創(chuàng)建實例:
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)造器永遠不會具有高于internal
的訪問級別,這意味著我們只能在定義其類型的模塊內(nèi)部使用它們艰猬。
最初横堡,這似乎是一個奇怪的限制,但它確實有其優(yōu)點冠桃,因為我們可以說應(yīng)該始終設(shè)計供公眾使用的顯式API命贴,而不必將它們與數(shù)據(jù)的內(nèi)部結(jié)構(gòu)聯(lián)系在一起。
因此,總而言之胸蛛,在以下情況下污茵,我們可以使用結(jié)構(gòu)體默認(rèn)生成的成員構(gòu)造器:
- 它的所有成員都是可見的或具有默認(rèn)值。
- 我們正在與定義該結(jié)構(gòu)體的模塊相同的模塊中創(chuàng)建一個實例葬项。
所有其他情況都要求我們至少到目前為止至少手動實現(xiàn)一個初始化程序泞当。
當(dāng)我們?yōu)榻Y(jié)構(gòu)體創(chuàng)建便利構(gòu)造器的時候,我們可以在 擴展extension
中聲明該便利構(gòu)造器民珍,這樣做的好處是襟士,當(dāng)我們定義一些便利構(gòu)造器方便初始化的同時,不會覆蓋編譯器生成的成員構(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
代碼會報錯陋桂,只剩下新聲明的便利構(gòu)造器。