swift init構造方法,convinience 及 convinience, swift和OC的初始化思路對比

語言: CN / TW / HK

在學習如何使用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

最後來一張圖,看下兩種初始化函式之間的區別:

image.png