iOS: 學習筆記, 值與參考型別(譯自: https://developer.apple.com/swift/blog/ Aug 15, 2014 Value and Reference Type
值和參考型別 Value and Reference Types
在Swift中,有兩種資料類型. 一是"值類型"(value type), 它是每一個執行個體都儲存有各自的資料,通常定義為struct, enum或tuple. 二是"參考型別"(reference types),它是多執行個體共用一份資料,這種類型通常定義為class. 在本文中,我們將展示值類型和參考型別各自的優點以及如何在二者之間選擇.
它們有什麼區別?
最基本的區別是 "值類型"通過拷貝(在賦值,初始化,參數傳遞中)會建立一個擁有獨立資料的執行個體, 例如:
// 值類型執行個體func value_type_example(){ struct S{var data:Int = -1} var a = S() var b = a // a 拷貝到 b a.data = 42 // 修改a, b不變 println("\(a.data), \(b.data)") // 列印 42, -1}
參考型別拷貝, 從另一方面來說, 是隱式的建立了一個共用執行個體. 在拷貝後, 兩個變數實際引用到了同一個執行個體, 也就是說修改第二個變數的值同樣會影響原始值, 例如:
func reference_type_example(){ class C{var data: Int = -1} var x = C() var y = x // x 拷貝到 y x.data = 42 // 修改x, 影響到y println("\(x.data), \(y.data)") // 列印 42, 42}可變性在安全的作用(The Role of Mutation in Safety)
一個選擇值類型(而不是參考型別)的主要原因是使代碼更簡單. 如果你總是得到一個唯一, 拷貝的執行個體, 你就可以確信其它代碼不會改變它. 這在多線程環境中非常有效(尤其是不同線程可能修改你的值, 這樣容易產生非常難以調試的錯誤).
因為兩者的區別在於資料改變, 因此在執行個體沒有可寫資料時, 值類型和參考型別會有相同的情境, 它們的作用是一致的.
你可能想到用值類型,然後,在另一個方面可能是一個不可變類. 這種情況下, 使用NSObject對象可以簡化問題, 它同時有值類型的優點. 現在,你可以在Swift中寫一個不可變類(只有不可變屬性,避免暴露能修改狀態的APIs). 實際上, 許多能用Cocoa類(比如NSURL)都設計為不可修改類. 然而, Swift當前並沒有提供任何語言機制強迫class不可變(比如子類). 只有struct和enum才強制不可變.
如何選擇呢?
如果你需要一個新類型, 你會選哪一種? 當你與Cocoa一起工作時, 許多APIs需要從NSObject子類化, 因此你只有用class. 在其它情況下, 這裡有一些指導方針:
使用值類型:
- 通過==比較執行個體資料
- 通過拷貝擁有獨立狀態
- 資料在多線程中使用
使用參考型別:
- 通過===比較執行個體資料
- 共用可修改狀態
在Swift中, Array,String和Dictionary都是值類型. 它們的行為非常象C中的簡單int值, 每個執行個體都有獨立的資料. 你不需要做任何其它事情(比如拷貝)來阻止其它代碼來修改資料. 重要的是, 你可以安全的線上程之間傳遞變數不需要處理同步問題. 在改善安全性的思路下, 這樣的模型將協助你編寫可預知的代碼.