# Swift里的值類型與引用類型
-----------------
> 翻譯:[老碼團隊翻譯組-Arya](http://weibo.com/littlekok/)
> 校對:[老碼團隊翻譯組-Jame](http://weibo.com/u/5241713117)
本頁包含內容:
[TOC=3,4]
### Swift里面的類型分為兩種:
* **值類型(Value Types)**:每個實例都保留了一分獨有的數據拷貝,一般以結構體 `(struct)`、`枚舉(enum)` 或者`元組(tuple)`的形式出現。
* **引用類型(Reference Type)**:每個實例共享同一份數據來源,一般以`類(class)`的形式出現。
在這篇博文里面,我們會介紹兩種類型各自的優點,以及應該怎么選擇使用。
#### 值類型與引用類型的區別
值類型和引用類型最基本的分別在復制之后的結果。當一個值類型被復制的時候,相當于創造了一個完全獨立的實例,這個實例保有屬于自己的獨有數據,數據不會受到其他實例的數據變化影響:
```swift
// 下面是一個值類型的例子
struct S { var data: Int = -1 }
var a = S()
var b = a // b是a的拷貝
a.data = 42 // 更改a的數據,b的不受影響
println("\(a.data), \(b.data)") // 輸出結果 "42, -1"
```
值類型就好像身份證復印件一樣,復印出來之后,修改原件上面的內容,復印件上的內容不會變。
另一方面,復制一個引用類型的時候,實際上是默默地創造了一個共享的實例分身,兩者是共用一套數據。因此修改其中任何一個實例的數據,也會影響到另外那個。
```swift
// 下面是一個引用類型的例子
class C { var data: Int = -1 }
var x = C()
var y = x // y是x的拷貝
x.data = 42 // 更改x的數據,等于同時修改了y
println("\(x.data), \(y.data)") // 輸出結果 "42, 42"
```
#### Mutation(修改)在安全中扮演的角色
值類型較引用類型來說,會讓你更容易在大量代碼中理清狀況。如果你總是得到一個獨立的拷貝出來的實例,你就可以放心它不會被你app里面的其他部分代碼默默地修改。這在多線程的環境里面是尤為重要的,因為另外一個線程可能會在暗地里修改你的數據。因此可能會造成嚴重的程序錯誤,這在調試過程中非常難以排除。
由于差別主要在于修改數據的后果,那么當實例的數據只讀,不存在需要更改的情況下,用哪種類型都是沒有分別的。
你可能在想,有的時候我可能也需要一個完全不變的類。這樣使用`Cocoa NSObject`對象的時候會比較容易,又可以保留值語義的好處。在今天,你可以通過只使用不可變的存儲屬性,和避開任何可以修改狀態的API,用Swift寫出一個不可變類`(immutable class)`。實際上,很多基本的Cocoa類,例如`NSURL`,都是設計成不可變類的。然而,Swift語言目前只強制`struct`和`enum`這種值類型的不可變性,對類這種引用類型則沒有。(例如還不支持強制將子類的限制為不可變類)
#### 如何選擇類型?
所以當我們想要建立一個新的類型的時候,怎么決定用值類型還是引用類型呢?當你使用Cocoa框架的時候,很多API都要通過NSObject的子類使用,所以這時候必須要用到引用類型class。在其他情況下,有下面幾個準則:
* **什么時候該用值類型**:
* 要用==運算符來比較實例的數據時
* 你希望那個實例的拷貝能保持獨立的狀態時
* 數據會被多個線程使用時
* **什么時候該用引用類型(class)**:
* 要用==運算符來比較實例身份的時候
* 你希望有創建一個共享的、可變對象的時候
在Swift里面,數組(Array)、字符串(String)、字典(Dictionary)都屬于值類型。它們就像C語言里面簡單的int值,是一個個獨立的數據個體。你不需要花任何功夫來防范其他代碼在暗地里修改它們。更重要的是,你可以在線程之間安全的傳遞變量,而不需要特地去同步。在Swift高安全性的精神下,這個模式會幫助你用Swift寫出更可控的代碼。
-----------------
本章節不是老碼的原創,老碼認真的閱讀了蘋果的官方博客,且自己的練習總結,如果小伙伴們費了吃奶的勁還是看不懂,請找度娘谷歌,還是看不懂請到老碼[官方微博](http://weibo.com/u/5241713117)咆哮。
##### 本文由翻譯自Apple Swift Blog :[Value and Reference Types](https://developer.apple.com/swift/blog/?id=10)
- 關于
- 歡迎使用 Swift
- 關于 Swift
- Swift 初見
- Swift 版本歷史記錄
- Swift 1.0 發布內容
- Swift 教程
- 基礎部分
- 基本運算符
- 字符串和字符
- 集合類型
- 控制流
- 函數
- 閉包
- 枚舉
- 類和結構體
- 屬性
- 方法
- 下標
- 繼承
- 構造過程
- 析構過程
- 自動引用計數
- 可選鏈
- 錯誤處理
- 類型轉換
- 嵌套類型
- 擴展
- 協議
- 泛型
- 訪問控制
- 高級運算符
- 語言參考
- 關于語言參考
- 詞法結構
- 類型
- 表達式
- 語句
- 聲明
- 特性
- 模式
- 泛型參數
- 語法總結
- 蘋果官方Blog官方翻譯
- Access Control 權限控制的黑與白
- 造個類型不是夢-白話Swift類型創建
- WWDC里面的那個“大炮打氣球”
- Swift與C語言指針友好合作
- 引用類型和值類型的恩怨
- 訪問控制和Protected
- 可選類型完美解決占位問題