Swift 3 基礎 — Class (part 3–1.)

BoShi Lee 
5 min readMar 15, 2017

Class Initializer: Designated , Convenience, Implicit, Required

Class 的初始化一直是很多初心者會遇到很多的初始化陷阱(包括我自己),有時候明明都已經給定所有的初始值了,編譯器卻怎麼都還是報錯??

這其中到底有什麼學問在裡面,讓我用切身之痛來一一為大家說明吧。

在看這篇文章之前,請先了解 initializer 的基礎,可以到我的文章先過一遍 “Swift 3 基礎 — Initializer”。

首先,先把初始化分成兩個部分來說明:

  1. 初始化在 base class/ superclass(本章節)
  2. 初始化在 subclass

初始化在 base class/ superclass

Designated Initializer:

在 Class 裡的所有的 stored properties 都要有初始值,我們會在 stored properties 後面直接賦予初始值,或者是明確的定義 initializer ,這個 initializer 可以稱作 designated initializer 。

在沒有設定任何自定義的 initializer 的情況下,系統預設的 implicit initializer init() 也算是其中一種 designated initializer :

Designated initializer 裡不可以self.init(...) 來指定呼叫同個 class 中的其他 initializer,這樣做是不合法的。

Convenience initializer:

Convenience initializer 是一個 initializer 加上前綴 convenience 。他就是一個委派初始化 (Delegating initializer),且必須委派到 designated initializer,且必須是同一個 class 的 designated initializer,下圖是一個錯誤的 Convenience initializer 的宣告方法:

沒有委派到 designated initializer 的錯誤

合法的的宣告應為:

Implicit Initializer

在還沒有任何的 stored properties,或者是 stored properties 有自己的初始值,以及沒有任何的 explicit designated initializer 的情況下,會自動產生一個 initializer 且這個就是 designated initializer 。

讓我們看看以下的範例,讓各位更能了解各個初始化的使用方法:

這個 class 的 stored properties 有自己的初始值,且他的 implicit init() 就是 designated initializer:

這個 class 雖然 stored properties 有自己的初始值,但已經有了 designated initializer,所以不能再使用 init() :

這個 class 的 stored properties 有初始值,它的 explicit initializer 是 convenience init ,且沒有明確定義 designated initializer,所以自動產生出 init() ,再來,這個 convenience init 可直接委派(delegate)到 init()

這個 class 的 stored properties 沒有給初始值,必須明確的宣告 designated initializer,且 implicit initializer 就不能再使用了:

這個 class 的 stored properties 沒有給初始值,有明確的宣告 designated initializer,但多了兩個 convenience initializer 追朔至 designated initializer:

可以試著把 Cat 實例化,並看看各個 init 被呼叫的流程為何,例如:

有兩點要提醒各位:

  1. Designated initializer 不能呼叫 self直到所有 stored properties 都被初始化完成(除非是為了給自己的 stored properties 賦予初始值)。
  2. Convenience initializer 必須委派到 designated initializer,且必須是同一個 class 的 designated initializer,且被 convenience initializer 修改到的 stored properties 必須為 var

Superclass / base class 的初始化就到這邊,下一篇會提到 subclass 的初始化,如果對以上內容有什麼建議或指教的地方,麻煩請下方留言或臉書留言。

謝謝您的閱讀!

--

--