翻譯:老碼團(tuán)隊(duì)翻譯組-Arya 校對(duì):老碼團(tuán)隊(duì)翻譯組-Jame
本頁(yè)包含內(nèi)容:
(struct)、枚舉(enum) 或者 元組(tuple)的形式出現(xiàn)。類(class)的形式出現(xiàn)。在這篇博文里面,我們會(huì)介紹兩種類型各自的優(yōu)點(diǎn),以及應(yīng)該怎么選擇使用。
值類型和引用類型最基本的分別在復(fù)制之后的結(jié)果。當(dāng)一個(gè)值類型被復(fù)制的時(shí)候,相當(dāng)于創(chuàng)造了一個(gè)完全獨(dú)立的實(shí)例,這個(gè)實(shí)例保有屬于自己的獨(dú)有數(shù)據(jù),數(shù)據(jù)不會(huì)受到其他實(shí)例的數(shù)據(jù)變化影響:
// 下面是一個(gè)值類型的例子
struct S { var data: Int = -1 }
var a = S()
var b = a // b 是 a 的拷貝
a.data = 42 // 更改 a 的數(shù)據(jù),b 的不受影響
println("\(a.data), \(b.data)") // 輸出結(jié)果 "42, -1"
值類型就好像身份證復(fù)印件一樣,復(fù)印出來(lái)之后,修改原件上面的內(nèi)容,復(fù)印件上的內(nèi)容不會(huì)變。
另一方面,復(fù)制一個(gè)引用類型的時(shí)候,實(shí)際上是默默地創(chuàng)造了一個(gè)共享的實(shí)例分身,兩者是共用一套數(shù)據(jù)。因此修改其中任何一個(gè)實(shí)例的數(shù)據(jù),也會(huì)影響到另外那個(gè)。
// 下面是一個(gè)引用類型的例子
class C { var data: Int = -1 }
var x = C()
var y = x // y 是 x 的拷貝
x.data = 42 // 更改 x 的數(shù)據(jù),等于同時(shí)修改了 y
println("\(x.data), \(y.data)") // 輸出結(jié)果 "42, 42"
值類型較引用類型來(lái)說(shuō),會(huì)讓你更容易在大量代碼中理清狀況。如果你總是得到一個(gè)獨(dú)立的拷貝出來(lái)的實(shí)例,你就可以放心它不會(huì)被你 app 里面的其他部分代碼默默地修改。這在多線程的環(huán)境里面是尤為重要的,因?yàn)榱硗庖粋€(gè)線程可能會(huì)在暗地里修改你的數(shù)據(jù)。因此可能會(huì)造成嚴(yán)重的程序錯(cuò)誤,這在調(diào)試過(guò)程中非常難以排除。
由于差別主要在于修改數(shù)據(jù)的后果,那么當(dāng)實(shí)例的數(shù)據(jù)只讀,不存在需要更改的情況下,用哪種類型都是沒(méi)有分別的。
你可能在想,有的時(shí)候我可能也需要一個(gè)完全不變的類。這樣使用 Cocoa NSObject 對(duì)象的時(shí)候會(huì)比較容易,又可以保留值語(yǔ)義的好處。在今天,你可以通過(guò)只使用不可變的存儲(chǔ)屬性,和避開任何可以修改狀態(tài)的 API,用 Swift 寫出一個(gè)不可變類 (immutable class)。實(shí)際上,很多基本的 Cocoa 類,例如 NSURL,都是設(shè)計(jì)成不可變類的。然而,Swift 語(yǔ)言目前只強(qiáng)制 struct 和 enum 這種值類型的不可變性,對(duì)類這種引用類型則沒(méi)有。(例如還不支持強(qiáng)制將子類的限制為不可變類)
所以當(dāng)我們想要建立一個(gè)新的類型的時(shí)候,怎么決定用值類型還是引用類型呢?當(dāng)你使用 Cocoa 框架的時(shí)候,很多 API 都要通過(guò) NSObject 的子類使用,所以這時(shí)候必須要用到引用類型 class。在其他情況下,有下面幾個(gè)準(zhǔn)則:
什么時(shí)候該用值類型:
在 Swift 里面,數(shù)組(Array)、字符串(String)、字典(Dictionary)都屬于值類型。它們就像 C 語(yǔ)言里面簡(jiǎn)單的 int 值,是一個(gè)個(gè)獨(dú)立的數(shù)據(jù)個(gè)體。你不需要花任何功夫來(lái)防范其他代碼在暗地里修改它們。更重要的是,你可以在線程之間安全的傳遞變量,而不需要特地去同步。在 Swift 高安全性的精神下,這個(gè)模式會(huì)幫助你用 Swift 寫出更可控的代碼。
本章節(jié)不是老碼的原創(chuàng),老碼認(rèn)真的閱讀了蘋果的官方博客,且自己的練習(xí)總結(jié),如果小伙伴們費(fèi)了吃奶的勁還是看不懂,請(qǐng)找度娘谷歌,還是看不懂請(qǐng)到老碼官方微博咆哮。