值類型(Value)與引用類型(Reference)
Swift 中結構體(struct)可定義屬性與方法,能夠指定初始化方法,實現協議,除了繼承,類(class)能作的,結構體幾乎都能作,那麼何時用結構體,何時用類就成了個問題,換句話說,就是在 Swift 中,什麼狀況應該用值類型,什麼狀況下用引用類型?
- 值類型:結構體(Struct)、枚舉(Enum)、元組(Tuple)
- 引用類型:類(Class)、函數(Function)
語義
- 值類型:變量與其所賦值分配的數據(值)邏輯統一,通常將其視爲儲存在棧(Stack)上,但實際上,一部分數據在 CPU 寄存器,其它一部分仍是分配在堆(Heap)上。能夠感性地將其理解爲,值類型的數據(值)被包含在了變量中,不可以單獨被操做。
- 引用類型:與值類型正好相反,變量與其分配的數據(實例)是分離的,引用類型的實例分配在堆(Heap)上,變量分配在棧上,僅持有該實例在內存中的地址,能夠有多個變量指向同一個實例,該實例可獨立地被其中任意指向它的變量操做。
struct CatStruct {
var name: String
}
let a = CatStruct(name: "Whiskers")
var b = a
b.name = "Fluffy"
print(a.name)
print(b.name)
class CatClass {
init(name: String) {
self.name = name
}
var name: String
}
let x = CatClass(name: "Whiskers")
let y = x
y.name = "Fluffy"
print(x.name)
print(y.name) 複製代碼
可變性(Mutability)概念的不一樣
- 區分變量(variable)可變性與實例(instance)可變性
- 因爲值類型,變量與實例在邏輯上是統一體,所以值類型的變量可變性,即其實例的可變性
- 引用類型,變量與其所指向的實例是分離的,所以變量的可變性,僅僅表明其始終指向同一實例,不表明其實例的可變性,其實例中的具體數據(屬性)等仍保持其自身的可變性。
值類型的特性
- 基於屬性的可等性(Attribute-based equality)
- 沒有身份標識與生命週期(Lack of Identity or lifecycle)
- 可替代性(Substitutability)
- 以上三個特性總結下來就是:5 美圓就是 5 美圓,到哪兒都是 5 美圓
值類型的優勢
- 高效:引用類型在堆上分配,相比棧上分配開支更大。Swift 中,值類型基於其特性實現了 copy on write,即當可變值類型真正發生改變那一刻時纔會爲其分配內存空間。
- 無反作用(可預測):不一樣於引用類型的實例可被多個變量引用並操做,值類型的特性能夠有效避免代碼的反作用。
- 線程安全
- 沒有內存泄露的問題
- 易測試
值類型與引用類型在應用開發中如何設計使用
- 引用類型用於構建有身份標識(identity)的模型實體(model entity)
-
- 若該狀況下采用值類型,則易形成同一身份標識的數據(屬性)不一致問題
- 值類型用於封裝狀態,暴露行爲,表述業務邏輯
- 使用環境很是重要
- 基於屬性的可等性的測試
- 值類型與引用類型的組合使用
-
總結
Swift 中提供了強大而高效的值類型,讓咱們的一部分代碼可以更高效、無反作用,而且線程安全。在理解了值類型與引用類型的區別的前提下,組合這兩種數據類型,更好更高效地達成應用目標。