Swift基礎 — Class 和 Structure OOP 和 POP

ChunYi LI
One Two Swift
Published in
7 min readMay 21, 2018

在2014年蘋果開發者年會,蘋果很興奮地推出了自家了程式語言,蘋果在自家的電子書上(App Development With Swift)說到他們當初他們當初設計Swift是以這三項特色為目標。

Safe、 Fast 、Expressive

在接觸Swift也有幾個月的時間,這個議題是讓我很困擾的部分,通常也是很多剛接觸這個語言的新手會碰到的問題也就是 Structure 和 Class 的差別。所以特別寫了這篇,讓自己有機會整理一下觀念。

相同之處

1. 擁有自己的屬性 (property)及方法 (function)
2.
可以自訂建構子 (initializer)

不同之處

1. Structure 無法繼承
2. Structure 擁有成員建構子 (Memberwise Initializer)
3. Structure 是 Value Type , Class 是 Reference Type
4.Structure不能直接修改內部屬性,如果要修改必須加上 mutating

在 Swift裡,幾乎所有 Class 能夠辦到的事情 ,Structure 都能辦到……
到底為何Apple要創造兩個這麼相似的東西!
在查詢資料的時候發現這個問題要回溯到Apple 在發明這項語言的目標。

安全、快速、易讀

這三項是 Swift 眾所皆知三大特色,我個人認為蘋果是基於安全及快速的原因要在 Swift 裡大力推廣 Structure。
其緣由要追溯到從1970年使用至今的物件導向設計( Object Oriented Programming 以下簡稱 OOP ),為了解決 OOP 既有的問題,蘋果大膽的提出了協定導向這個觀念(Protocol-Oriented Programming 以下簡稱 POP )。

在2015 WWDC 中的這場講座就是在分享協定導向,其中講者講述到說自己在過去也是個 OOP 的愛好者,直到遇到一位前輩說他有多不屑物件導向設計並且講述使用物件導向會出現的問題。

Implicit Sharing

Class 是 reference type 所以會有所謂的值不正常覆蓋,何謂值不正常覆蓋我以簡單的程式碼表示

我創造了一個 Book 類別,再來我又寫了一個 bookOne 物件,他的名稱為哈利波特,再來我把 bookOne 這個物件指派給 bookTwo,並且將 bookTwo 的書名改為飢餓遊戲,最後分別把兩個書名印出來。

這時候問題發生了,明明我改的是第二本書的書名,怎麼第一本書的書名也變成了飢餓遊戲?

下面這張圖可以解釋此種現象

由於 reference type 的特性,第一本及第二本書都指向相同的記憶體位置,所以當我改動其中一個物件時,另一個物件實體的值也會更動。因為我們至始至終都是改動同一個東西。

再來我們來看 Structure 的呈現

這時候我只有改動到第二本書的書名而已

因為這時候我將 bookOne 指派給 bookTwo,其實在背後我已經創造了另一個記憶體空間,所以這兩本書是獨立的兩個物件。

由此就可以看出 Struct 所屬的 Value Type 解決了值不正常覆蓋的問題。這頁顧全了Swift的其中一個特色 【 安全 】 。

Value Don’t Share.
( That’s a Good Thing )
Classes ? They Overshare

Inheritance All Up In Your Business

接下來講者繼續講到了 Class 的繼承問題,我就我所能理解的部分來論述。他說 Class 只能有一個父類別,你必須在你定義一個需要繼承父類別的新類別時就要先確定要繼承哪一個父類別,不能夠之後再加或是有更彈性的作法。

但是我不確定 C 與 C++的多重繼承適不適用在這裡,但我還是記錄一下,日後有了解之後再來做修正。但在 JAVA 我比較能確定的是可以利用介面來實作多重繼承的問題,但依然不能解決下面的問題。

Class 的繼承必須全部繼承,包括型別及方法,就算是子類別不需要這麼多東西也都得全部繼承。就因為你繼承了父類別的所有型別,就代表你也必須一併的初始化他們,這種做法比較沒有彈性可言。

POP如何解決這種問題呢?

這時候 Protocol-Oriented Programming 就發揮非常強大的作用。

如果我想要做到類似多重繼承的這種效果,我只要需要去實作 protocol ,像我寫的範例我有一個 Book 實體它實做了 Discount 和 Page,此時我們不用繼承就可以知道 Book 是可以打折的還有可以知道其頁數。但另一個實體 Fruit 在設計時就不需要頁數,所以我們只有實做了 Discount。

如此一來 Protocols 不僅僅可以不斷的重複利用,也可以讓我們實作需要的部分就好。

看完了以上 POP 的介紹接下來我們要從Structure與Class的不同處來一一回答為何蘋果要創造。

1. Structure 無法繼承

因為傳統繼承關係太過笨重且不靈活,蘋果為解決此問題使用了Protocols的概念,大幅的改進了繼承的缺點。

2. Structure 擁有成員建構子 (Memberwise Initializer)

Swift除了安全、快速、易讀性之外還有簡單、現代化的特性,此處的成員建構子就是個很典型的例子。Struct 在你呼叫時就會給你成員建構子讓你填入外部參數達到初始化。

3. Structure 是 Value Type , Class 是 Reference Type

如我上面所講述,為了安全的緣故,蘋果大力的提倡身為Value Type的 Struct 以防值不正常覆蓋。

4. Structure不能直接修改內部屬性,如果要修改必須加上 mutating

安全、安全 還是安全

Structure 和 Class 使用時機

蘋果官方在他們的電子書是這樣推薦的

在這邊指出,在大部份時候蘋果鼓勵你使用 Struct ,直到你需要利用到 Class 才有的特性像是你需要使用到 Swift 的 Framework 像是 Foundation 或是 UIkit ,或是你需要不斷的在各處繼承同一個父類別。

從前輩那邊得到的建議是

structure的使用定位比較像是儲存資料。
class則是著重在流程控制,程式碼功能導向。

結語

所以以結果看來,Structure並不是被創造出來取代Class的而是為了讓Swift這個程式語言更加的安全、便利所使用。其中也有不少地方是因為 POP 讓Structure 在 Swift 中更大力地被推廣。所以兩個都有其優缺點,也沒有孰優孰劣,只需要開發者能夠徹底的了解他們的特性並且發揮他們100%效能。

以上就是一個剛接觸Swift不久的蔡逼八所整理的Struct 還有 Class 的比較,因為對Swift還有許多不了解的地方,所以可能內容會有誤,如果前輩們有看到什麼錯誤的地方還請手下留情,我玻璃心。如果發現有誤請在下方留言,如果覺得整理得不錯也給蔡逼八一點鼓勵。

--

--

ChunYi LI
One Two Swift

Hi this is Chunyi-Li from Taiwan, a junior iOS deveoper