Structures
struct
跟 enum
是 value type instance, value type 是指當被 assign 到 constant 或 variable,或當作參數傳遞到 function 時,他的值是被 copied 過去的,在 swift 裡面 intergers, floating-point numbers, booleans, strings, arrays and dictionaries 皆為 value type
struct SWeather {
var location: String
var minTemp: Double
var maxTemp: Double
}
let s = SWeather(location: "Taipei", minTemp: 12, maxTemp: 15)
接著定義一個 ss
來 assign to s
var ss = s
ss.minTemp = 10 # 設 minTemp 為 10
output:
(lldb) po s
▿ SWeather
- location : "Taipei"
- minTemp : 12.0 # s 的 minTemp 不會改變,因為做 assignment 時是複製一份相同的數值到 ss
- maxTemp : 15.0
(lldb) po ss
▿ SWeather
- location : "Taipei"
- minTemp : 10.0 # ss 的 minTemp 已變為 10
- maxTemp : 15.0
Classes
class
是 reference type instance, 不同於 structures,當被 assign 到 constant 或 variable,或當作參數傳遞到 function 時,會儲存一個參考位址 reference 到同一個實例
class CWeather {
var location: String?
var minTemp: Double = 0
var maxTemp: Double = 0
}
let c = CWeather()
c.location = "Taipei"
c.minTemp = 12
c.maxTemp = 15
定義一個 d
並指到 c
let d = c // 指向 c
d.minTemp = 13
output:
(lldb) po c
<CWeather: 0x600001367240> # class instance 被配置到參照位址中
(lldb) po c.minTemp
13.0 # c instance 的 minTemp 也被改為 13
(lldb) po d.minTemp
13.0
相同的地方
- 可定義 property 並保存值
- 可定義 methods
- 可自定義 subscripts 捷徑來存取 collection, list or sequence 的 member
- 可自定義 initializers
- 可使用 extension 來延伸功能性
- 可遵從 Protocols
不同的地方
Classes 還可以做到
- 繼承
- 可在 runtime 作類型轉換(Type casting)
- Deinitializers 可以釋放記憶體空間
- Reference count
Classes 雖然提供更多的功能與彈性但相對的也提升了程式的複雜度,若在一般使用情境下,建議使用 structures 跟 enumerations 來定義,可以減少擔心 memory leaks 或多緒執行下可能造成的 data racing (access/modify),而在適當的時機或需要時才使用 classes 來定義。
使用情境
使用 struct
的情境:
- 預設的建模方式,適用在大部分情況
- 透過 Protocols 為繼承和共享行為建模 (Protocols Oriented Programming)
- 不需要辨識不同 identity 時
使用 class
的情境:
- 需與 Objective-C 做互通
- 需要辨識不同的身份時,假設兩個 instances 有相同的 value 但可使用
===
來分辨不同的 identity - 不需要 Copying or comparing instances (e.g.,
Window
) - 實例的 lifetime 與外部影響有關 (e.g.,
TemporaryFile
) - 實例只是"接收器" 指向外部狀態的 write-only 管道 (e.g.
CGContext
)