默認構造器 和 結構體的逐一成員構造器
如果一個class或struct提供了默認值,同時沒有定義任何構造器那么會自動提供一個默認構造器(default initializers)。如:
class Person {
var firstName = "Nero"
var lastName = "Zuo"
}
let person = Person()
結構體的逐一成員構造器,
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) //逐一成員構造器
let circle1 = Circle() //默認構造器
指定構造器(Designated)和便利構造器(Convenience)
class Shape {
var lineWidth: CGFloat
init(lineWidth: CGFloat) {
self.lineWidth = lineWidth
}
convenience init() {
self.init(lineWidth: 1)
}
}
這里init(lineWidth: CGFloat)
是指定構造器,convenience init()
是便利構造器,使用convenience
關鍵字
繼承中的構造器
自動繼承構造器
如果子類沒有寫任何指定構造器,那么子類就繼承繼承父類的所有構造器,包括便利構造器,同時你可以增加遍歷構造器但不用重寫指定構造器
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)
注意:便利構造器一定要調用self的構造的,而不是super。這里看真好像調用了super的,但是這里Circle類自動繼承了父類的所有構造器。
如果子類把所有的指定構造器重寫了,那么父類的便利構造器也會自動繼承
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() //成功,父類的便利構造器繼承下來了
let circle2 = Circle(radius: 1) //成功
這里舉得例子不是很好,但能說明自動繼承,和下面的那段類似代碼對比看更好。
構造器的繼承和重寫
當你定義了一個的新的構造器時,那么在此構造器你必須新調用父類的指定構造器(待會兒說道構造過程時會具體講到)。
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()
都不能在子類里用了,因為沒有重寫。
重寫構造器只能重寫父類的指定的構造器,加上關鍵字override
。
兩段式構造過程

第一階段:
我的理解是類似不斷遞歸的過程,最下面的子類給自己新的存儲屬性賦值,然后調用父類的指定構造器(不能調用父類的便利構造器),父類的構造器也是這個過程,不斷往上,打到最上面時結束
第二階段:
此時可以使用self
,從上到下對對屬性進一步定制化。
一句話總結指定構造器和便利構造器是指定構造器縱向代理,遍歷構造器橫向代理
必要構造器(Required)
如果子類中重寫或定義了指定構造器,就必須在子類中實現這個必要構造器,且不需要加上override
關鍵字,只需要加上required
。
遇到最多的就是必要構造器就是required init?(coder aDecoder: NSCoder)
這個在iOS中,如UIView, UIViewController等中經常出現,遵循了NSCoding
協議,用于歸檔轉碼等。
可失敗構造器
類似這樣的是可失敗構造器,這個返回的是這個類的optional。
init?(){ }
淺見覺得調用這個(便利或指定)的構造器都需要是可失敗構造器