默認(rèn)構(gòu)造器 和 結(jié)構(gòu)體的逐一成員構(gòu)造器
如果一個class或struct提供了默認(rèn)值,同時沒有定義任何構(gòu)造器那么會自動提供一個默認(rèn)構(gòu)造器(default initializers)。如:
class Person {
var firstName = "Nero"
var lastName = "Zuo"
}
let person = Person()
結(jié)構(gòu)體的逐一成員構(gòu)造器,
struct Circle {
var center: CGPoint = CGPoint(x: 0, y: 2)
var radius: CGFloat = 2
}
let circle0 = Circle(center: CGPoint(x: 0, y: 0), radius: 1) //逐一成員構(gòu)造器
let circle1 = Circle() //默認(rèn)構(gòu)造器
指定構(gòu)造器(Designated)和便利構(gòu)造器(Convenience)
class Shape {
var lineWidth: CGFloat
init(lineWidth: CGFloat) {
self.lineWidth = lineWidth
}
convenience init() {
self.init(lineWidth: 1)
}
}
這里init(lineWidth: CGFloat)是指定構(gòu)造器,convenience init()是便利構(gòu)造器,使用convenience關(guān)鍵字
繼承中的構(gòu)造器
自動繼承構(gòu)造器
如果子類沒有寫任何指定構(gòu)造器,那么子類就繼承繼承父類的所有構(gòu)造器,包括便利構(gòu)造器,同時你可以增加遍歷構(gòu)造器但不用重寫指定構(gòu)造器
class Shape {
var lineWidth: CGFloat
init(lineWidth: CGFloat) {
self.lineWidth = lineWidth
}
convenience init() {
self.init(lineWidth: 1)
}
}
class Circle: Shape {
convenience init(value: Int) {
self.init()
//self.init(lineWidth: 1) //這同樣可以
}
}
let circle0 = Circle()
let circle1 = Circle(lineWidth: 2)
let circle2 = circle(value: 1)
注意:便利構(gòu)造器一定要調(diào)用self的構(gòu)造的,而不是super。這里看真好像調(diào)用了super的,但是這里Circle類自動繼承了父類的所有構(gòu)造器。
如果子類把所有的指定構(gòu)造器重寫了,那么父類的便利構(gòu)造器也會自動繼承
class Shape {
var lineWidth: CGFloat
init(lineWidth: CGFloat) {
self.lineWidth = lineWidth
}
convenience init() {
self.init(lineWidth: 1)
}
}
class Circle: Shape {
var radius: CGFloat
init(radius: CGFloat) {
self.radius = radius
super.init(lineWidth: 2)
}
override init(lineWidth: CGFloat) {
self.radius = 2
super.init(lineWidth: lineWidth)
}
}
let circle0 = Circle(lineWidth: 1) //成功
let circle1 = Circle() //成功,父類的便利構(gòu)造器繼承下來了
let circle2 = Circle(radius: 1) //成功
這里舉得例子不是很好,但能說明自動繼承,和下面的那段類似代碼對比看更好。
構(gòu)造器的繼承和重寫
當(dāng)你定義了一個的新的構(gòu)造器時,那么在此構(gòu)造器你必須新調(diào)用父類的指定構(gòu)造器(待會兒說道構(gòu)造過程時會具體講到)。
class Shape {
var lineWidth: CGFloat
init(lineWidth: CGFloat) {
self.lineWidth = lineWidth
}
convenience init() {
self.init(lineWidth: 1)
}
}
class Circle: Shape {
var radius: CGFloat
init(radius: CGFloat) {
self.radius = radius
super.init(lineWidth: 2)
}
}
let circle0 = Circle(lineWidth: 1) //錯誤,不能初始化,因為沒有重寫
let circle1 = Circle() //錯誤,不能初始化
let circle2 = Circle(radius: CGFloat) //成功
這里的父類的init(lineWidth: CGFloat)和convenience init()都不能在子類里用了,因為沒有重寫。
重寫構(gòu)造器只能重寫父類的指定的構(gòu)造器,加上關(guān)鍵字override。
兩段式構(gòu)造過程
第一階段:
我的理解是類似不斷遞歸的過程,最下面的子類給自己新的存儲屬性賦值,然后調(diào)用父類的指定構(gòu)造器(不能調(diào)用父類的便利構(gòu)造器),父類的構(gòu)造器也是這個過程,不斷往上,打到最上面時結(jié)束
第二階段:
此時可以使用self,從上到下對對屬性進(jìn)一步定制化。
一句話總結(jié)指定構(gòu)造器和便利構(gòu)造器是指定構(gòu)造器縱向代理,遍歷構(gòu)造器橫向代理
必要構(gòu)造器(Required)
如果子類中重寫或定義了指定構(gòu)造器,就必須在子類中實現(xiàn)這個必要構(gòu)造器,且不需要加上override關(guān)鍵字,只需要加上required。
遇到最多的就是必要構(gòu)造器就是required init?(coder aDecoder: NSCoder)
這個在iOS中,如UIView, UIViewController等中經(jīng)常出現(xiàn),遵循了NSCoding協(xié)議,用于歸檔轉(zhuǎn)碼等。
可失敗構(gòu)造器
類似這樣的是可失敗構(gòu)造器,這個返回的是這個類的optional。
init?(){ }
淺見覺得調(diào)用這個(便利或指定)的構(gòu)造器都需要是可失敗構(gòu)造器