在Swift中對象的初始化方法分爲兩種,指定構造器(Designated Initializers)和便利構造器(Convenience Initializers)。記錄一下我對它的初步理解。swift
其實就是OC的init初始化方法。OC中通常初始化某個類(以Person爲例,屬性有name和age),使用以init開頭的方法,以下:安全
在.h中暴露出聲明方法。
//默認name="",age=0
- (instancetype)init;
//以name來初始化,默認age=0
- (instancetype)initWithName:(NSString *)name;
//賦值name和age來初始化
- (instancetype)initWithName:(NSString *)name age:(NSInteger)age;
複製代碼
實現方法以下:bash
在.m中寫方法實現。
// 便利構造器
- (instancetype)init {
return [self initWithName:@""];
}
// 便利構造器
- (instancetype)initWithName:(NSString *)name {
return [self initWithName:name age:0];
}
// 指定構造器
- (instancetype)initWithName:(NSString *)name age:(NSInteger)age {
self = [super init];
if (!self) {
return nil;
}
_name = name;
_age = age;
return self;
}
複製代碼
而Swif中的三種也是這樣,init()以下。這裏我在ide
.swift中寫方法
//此處,我給name和age初始值。
var name: String = ""
var age: Int = 0
// 便利構造器
override convenience init() {
self.init(name: "haha")//此處默認名字是haha,是爲了方便看出子類可繼承convenience init方法。
}
// 便利構造器
convenience init(name: String) {
self.init(name: name, age:0)
}
// 指定構造器
init(name: String, age: Int) {
super.init()
self.name = name
self.age = age
}
複製代碼
寫Swift這段代碼時,有以下問題函數
注意:Swift不一樣於OC的init,它沒有返回值。在這一過程裏面初始全部的存儲屬性和其它的必要初始化操做。 ui
存儲屬性,在調用任何方法(好比子類調父類的super.init,或者調本類的方法)以前,都應該確保在本類對存儲屬性進行初始化。若是name和age並無給初始值,則代碼應該改爲以下,以init(name: String, age: Int)爲例:spa
init(name: String, age: Int) {
self.name = name
self.age = age
super.init()
}
複製代碼
這是因爲Swift的內存安全,在調用父類構造方法以前,確保對本類的全部存儲屬性進行初始化。採用了Two-Phase Initialization(兩段式構造)模型來實現內存安全。code
Github源碼文檔有一處是三段式構造,第三段:若是還有其它操做,可執行其它方法來完成初始化。對象
指定構造器,這是一個類最主要的方法,若是有父類,則子類的指定構造器方法必需要調父類的指定構造方法與父類關聯。好比上面的Swift的Person類,繼承
init(name: String) {
super.init()
self.name = name
}
複製代碼
便利構造器,便捷生成實例的方法,對指定構造器的參數作了選擇,可不用傳那麼多參數。
class Boy: Person {
var girlFriendName: String
override init(name: String, age: Int) {
self.girlFriendName = "girl"
super.init(name: name, age: age)
print("我完成了init")
}
}
複製代碼
若是Person裏面還有另外一個指定構造方法,則Boy類裏面也須要重寫此方法。不然調用Boy.init()會報錯。調用Boy.init()的構造過程以下: