swift init構造方法,convinience 及 convinience, swift和OC的初始化思路對比
在學習如何使用swift的init構造方法的具體用法前,我們先設想一個場景: 有個學生系統包含學生類,學生有名字和年齡,名字是必填的,年齡是非必填的,如何設計這個類呢?
OC是如何完成的?
我們先使用OC來完成,方便後面對比:
先看下類設計:
``` @interface LFStudent : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@end ```
然後我們增加下初始化方法,這裡我們要使用OC中特有的全能方法,然後為了方便使用者只需要初始化名稱的場景,我們會增加一個只包含name入參的函式,函式如下:
``` - (instancetype)initWithName:(NSString *)name age:(NSInteger)age { if (self = [super init]) { _name = name; _age = age; } return self; }
- (instancetype)initWithName:(NSString *)name { return [self initWithName:name age:-1]; } ``` 這裡注意,我們只使用了一個可以最終初始化的全能方法,而其他的方法,我們是呼叫這個全能方法來完成的,有了全能方法,能保證我們的類的初始化的最後都是收到一個入口
Swift 如何完成初始化
那麼如果使用swift要如何寫呢? swift中的init方法分為兩種,指定構造designated init和方便構造 convenience init
我們的第一反應可能是想和OC一樣,定一個類似全能方法,然後其他的初始化方法呼叫這個全能方法即可,但是很遺憾,swif中designated方法不能呼叫其他的designated方法,只能呼叫super.init,也就是說,以下的初始化是會報錯的:
``` init(name: String?, age : Int){ super.init() self.name = name self.age = age }
init(name: String?){ init(name: name, age : -1) //error } ```
convinience 和 designated
那如果我們要如何實現呢? 肯定是不希望重複定義多個重複設定屬性的函式,這樣收口有多個,很容易出現後期不一致的問題,這裡就要使用 convinience init了,swift規定,convenience 是可以呼叫指定構造 designated init的,所以我們通常會將designated做成全能方法(本來也是如此設定的),然後使用 convenience 來做修飾,提供方便快捷的構造方法,具體實現如下:
``` init(name: String?, age : Int){ super.init() self.name = name self.age = age }
convenience init(name: Stirng?){ self.init(name: name, age: -1) } ```
完成,convenience方法完美的解決了快速初始化的需求
注意事項
- swift的init定義不需要使用func修飾
- swift 初始化中 designated 為主初始化, 需要的話使用 convinience 來補充 ,convinience 可以呼叫designated, designated只能呼叫super
- swift的init不需要return
最後來一張圖,看下兩種初始化函式之間的區別: