在前幾篇介紹 Struct 與 Class 時,有提到一個是 Value Type,另一個則是 Reference Type,今天再仔細探究一下這兩者之間的差異以及使用情境。
Class 就是一個經典的 Reference Type,除此之外還有 Functions 以及 Closure 都是 Reference Type。
至於 Value Type,以之前舉的例子,Struct 就是 Value Type,像是 String、Array、Dictionary 都是以 Struct 來實作,所以都是 Value Type。在 Swift Standard Library 中可以發現,大量使用了 Value Type。
class Car {
var wheelNumber = 4
}
let car1 = Car()
let car2 = car1
car1.wheelNumber = 8
print(car2.wheelNumber) // 8
上面這個類別代表著這個車會有四個輪胎,假定我們透過實體化建立 car1
實體,這時候就會指向一個記憶體位址來給 car1
參考,此時我們在建立一個 car2
並且指派 car1
給它,這時候 car2
會指向與 car1
同一個記憶體位址。
所以他們兩個現在共享同一個記憶體位址,也因此當我們透過其中一個實體,來更改屬性 wheelNumber
,另外一個實體在呼叫時也會跟著更改。
至於 Value Type 就是另外一回事了,跟 Reference Type 完全不同,我們先來看一個簡單的範例:
var value1 = 100
var value2 = value1
value2 += 100
print(value1) // 100
print(value2) // 200
value2
變數的值是參考 value1,當 value2
改變數值時,value1
不會受到影響,因為這兩個變數的記憶體空間指向不同位址,如果把上面的 Car 類別改成 Struct 看看:
struct Car {
var wheelNumber = 4
}
var car1 = Car()
var car2 = car1
car1.wheelNumber = 8
print(car2.wheelNumber) // 4
在 Reference Type 中,儘管在宣告實體時,用的是 let 來宣告為常數,還是可以透過實體來修改屬性值,但是在 Value Type 如果這樣做,是更改不了屬性值的,為什麼會這樣?
let
宣告的實體,不能再被指派其他資料,但是可以更改實體本身的屬性或是方法。let
宣告的實體,不僅不能再被指派其他資料,連同實體本身的屬性也都會被視為常數而不能被更改,儘管屬性宣告時是使用 var
。對於 Value Type 以及 Reference Type 該如何來取捨及使用呢?
==
來比較值的時候struct People {
var name: String
}
let people1 = People(name: "安竹")
let people2 = People(name: "安竹")
在這種情況下,我們可以說 people1
跟 people2
相等,我們可以合理使用 ==
( 需要遵循 Equatable Protocol
) 來判斷兩者資料是否相符。
struct People {
var name: String
}
var people1 = People(name: "安竹")
var people2 = People(name: "安竹")
people1.name = "皮皮"
print(people2.name) // 安竹
當 people1 已經更改名稱時,並不會影響到 people2。
===
來比較值的時候class People {
var name: String = "安竹皮皮"
}
var people1 = People()
var people2 = people1
print(people2 === people1) // true
可以透過 ===
來檢查兩者記憶體儲存位址是否相同,進而判斷兩個物件相同與否。
class 午餐 {
var 員工配額 = 240
}
class 員工 {
var 午餐費用: 午餐
init(午餐費用: 午餐) {
self.午餐費用 = 午餐費用
}
}
let 午餐費用 = 午餐()
let 員工甲 = 員工(午餐費用: 午餐費用)
let 員工乙 = 員工(午餐費用: 午餐費用)
print(員工甲.午餐費用.員工配額) // 240
print(員工乙.午餐費用.員工配額) // 240
午餐
作為一個 class,並且再宣告一個 class 員工
,每個員工都有一筆午餐費用,這是參考 午餐
class,每人的員工午餐配額都是一致的,所以這樣就不會有人配額比較高,而造成內心小劇場。