類和結構體對比
Swift 中類和結構體有很多共同點。共同處在于:
- 定義屬性用于存儲值
- 定義方法用于提供功能
- 定義下标操作使得可以通過下智語法來通路執行個體所包含的值
- 定義構造器用于生成初始化值
- 通過擴充以增加預設實作的功能
- 實作協定以提供某種标準功能
與結構體相比,類還有如下的附加功能:
- 繼承允許一個類繼承另一個類的特征
- 類型轉換允許在運作時檢查和解釋一個類執行個體的類型
- 析構器允許一個類執行個體釋放任何其所被配置設定的資源
- 引用計數允許對一個類的多次引用
注意 結構體總是通過被複制的方式在代碼中傳遞,不使用引用計數。
struct SomeStructure {
//定義結構體
var width = 0
var height = 0
}
class SomeClass {
//定義類
var someStruct = SomeStructure()
var name: String?
var isClass = true
}
結構體和枚舉是值類型
值類型被賦予給一個變量、常量或者被傳遞給一個函數的時候,其值會被拷貝。
在之前的章節中,我們已經大量使用了值類型。實際上,在 Swift 中,所有的基本類型:整數(Integer)、浮點數(floating-point)、布爾值(Boolean)、字元串(string)、數組(array)和字典(dictionary),都是值類型,并且在底層都是以結構體的形式所實作。
在 Swift 中,所有的結構體和枚舉類型都是值類型。這意味着它們的執行個體,以及執行個體中所包含的任何值類型屬性,在代碼中傳遞的時候都會被複制。
let someResolution = SomeStructure()
print("the width of someResolution is \(someResolution.width)")
let wh = SomeStructure(width: 375,height:668)
var cinema = wh
cinema.width = 320
print(wh.width)//375
類是引用類型
與值類型不同,引用類型在被賦予到一個變量、常量或者被傳遞到一個函數時,其值不會被拷貝。是以,引用的是已存在的執行個體本身而不是其拷貝。
let someclass = SomeClass()
print("the width of someclass is \(someclass.someStruct.width)")//0
someclass.someStruct.width = 1080
print("the width of someclass is \(someclass.someStruct.width)")//0
let newClass = someclass
print(someclass.someStruct.width)//1080
newClass.someStruct.width = 375
print(someclass.someStruct.width)375
類和結構體的選擇
在你的代碼中,你可以使用類和結構體來定義你的自定義資料類型。
然而,結構體執行個體總是通過值傳遞,類執行個體總是通過引用傳遞。這意味兩者适用不同的任務。當你在考慮一個工程項目的資料結構和功能的時候,你需要決定每個資料結構是定義成類還是結構體。
按照通用的準則,當符合一條或多條以下條件時,請考慮建構結構體:
- 該資料結構的主要目的是用來封裝少量相關簡單資料值。
- 有理由預計該資料結構的執行個體在被指派或傳遞時,封裝的資料将會被拷貝而不是被引用。
- 該資料結構中儲存的值類型屬性,也應該被拷貝,而不是被引用。
- 該資料結構不需要去繼承另一個既有類型的屬性或者行為。
舉例來說,以下情境中适合使用結構體:
- 幾何形狀的大小,封裝一個
屬性和width
屬性,兩者均為height
類型。Double
- 一定範圍内的路徑,封裝一個
屬性和start
屬性,兩者均為length
類型。Int
- 三維坐标系内一點,封裝
,x
和y
屬性,三者均為z
類型。Double
在所有其它案例中,定義一個類,生成一個它的執行個體,并通過引用來管理和傳遞。實際中,這意味着絕大部分的自定義資料構造都應該是類,而非結構體。