相同點(diǎn):
1.定義屬性用于存儲(chǔ)值 (property
)
2.定義方法用于提供功能 (function
)
3.定義下標(biāo)操作使得可以通過(guò)下標(biāo)語(yǔ)法來(lái)訪(fǎng)問(wèn)實(shí)例所包含的值 (subscript
)
4.定義構(gòu)造器用于生成初始化值 (initializers
)
5.通過(guò)擴(kuò)展以增加默認(rèn)實(shí)現(xiàn)的功能 (extension
)
6.實(shí)現(xiàn)協(xié)議以提供某種標(biāo)準(zhǔn)功能 (protocol
)
不同點(diǎn):
1.class是引用類(lèi)型;struct是值類(lèi)型
2.class支持繼承;struct不支持繼承
3.class聲明的方法修改屬性時(shí)不需要mutating
關(guān)鍵字俊柔;struct需要
4.class中每一個(gè)成員變量都必須被初始化框往,否則編譯器會(huì)報(bào)錯(cuò)匙赞,而struct
不需要屡穗,編譯器會(huì)自動(dòng)幫我們生成init函數(shù)
,給變量賦一個(gè)默認(rèn)值
5.class支持引用計(jì)數(shù)(reference counting)(允許對(duì)一個(gè)類(lèi)的多次引用)番枚,struct不支持
6.class支持type casting(類(lèi)型轉(zhuǎn)換)(允許在運(yùn)行時(shí)檢查和解釋一個(gè)類(lèi)實(shí)例的類(lèi)型)法严,struct不支持
7.class支持deinitializers(析構(gòu)器)(允許一個(gè)類(lèi)實(shí)例釋放任何其所被分配的資源),struct不支持
8.變量賦值方式不同(深淺copy)葫笼,class淺拷貝深啤,struct深拷貝,class的賦值是傳遞引用渔欢,struct則是copy傳值,不是使用引用計(jì)數(shù)墓塌。
9.內(nèi)存管理:struct存儲(chǔ)在stack中,class存儲(chǔ)在heap中奥额、
10.方法派發(fā)方式:struct的方法調(diào)用是靜態(tài)綁定
苫幢,而class的方法調(diào)用是動(dòng)態(tài)實(shí)現(xiàn)
Tip: class的對(duì)象是引用類(lèi)型,而struct是值類(lèi)型垫挨。所以class的賦值是傳遞引用韩肝,則是copy傳值,不是使用引用計(jì)數(shù)。
class為了支持的額外功能則會(huì)增加其復(fù)雜性九榔。一般,更傾向使用選擇struct和enum,因?yàn)樗麄兏菀桌斫?而class哀峻,則在合適和必要的時(shí)候使用。實(shí)際上哲泊,這意味著大多數(shù)的自定義數(shù)據(jù)類(lèi)型定義為struct和enum就可以
了剩蟀。
class和struct的選擇
struct實(shí)例總是通過(guò)值傳遞,class實(shí)例總是通過(guò)引用傳遞切威。這意味兩者適用不同的任務(wù)育特。當(dāng)你在考慮一個(gè)工程項(xiàng)目的數(shù)據(jù)結(jié)構(gòu)和功能的時(shí)候,你需要決定每個(gè)數(shù)據(jù)結(jié)構(gòu)是定義成struct還是class先朦。
按照通用的準(zhǔn)則缰冤,當(dāng)符合一條或多條以下條件時(shí),請(qǐng)考慮構(gòu)建struct
:
- 該數(shù)據(jù)結(jié)構(gòu)的主要目的是用來(lái)封裝少量相關(guān)簡(jiǎn)單數(shù)據(jù)值喳魏。
- 有理由預(yù)計(jì)該數(shù)據(jù)結(jié)構(gòu)的實(shí)例在被賦值或傳遞時(shí)棉浸,封裝的數(shù)據(jù)將會(huì)被拷貝而不是被引用。
- 該數(shù)據(jù)結(jié)構(gòu)中儲(chǔ)存的值類(lèi)型屬性刺彩,也應(yīng)該被拷貝迷郑,而不是被引用枝恋。
- 該數(shù)據(jù)結(jié)構(gòu)不需要去繼承另一個(gè)既有類(lèi)型的屬性或者行為。
- 使用struct和protocol來(lái)實(shí)現(xiàn)model繼承和共享行為嗡害,如下代碼所示:
protocol AnimalCommonProtocol {
var name: String? { get set }
var weight: Double { get set }
func run()
}
struct Cat : AnimalCommonProtocol {
func run() {
print("cat run")
}
var name: String?
var weight: Double
var gender: String?
}
struct Dog : AnimalCommonProtocol {
func run() {
print("dog run")
}
var name: String?
var weight: Double
var type: String?
}
總結(jié)起來(lái)就是一句話(huà):能使用struct就不要使用class
為什么優(yōu)選struct:
- 使用struct不需要考慮內(nèi)存泄漏和多線(xiàn)程讀寫(xiě)的問(wèn)題鼓择,因?yàn)樵趥鬟f值的時(shí)候它會(huì)進(jìn)行值的copy
- struct存儲(chǔ)在stack中,class存儲(chǔ)在heap中就漾,struct更快
- 在運(yùn)行時(shí),struct在性能方面更優(yōu)于class念搬,原因是struct的方法調(diào)用是靜態(tài)綁定抑堡,而class的方法調(diào)用是動(dòng)態(tài)實(shí)現(xiàn)的。這就是盡可能得使用struct代替class的又一個(gè)好的原因朗徊。
恒等運(yùn)算符
因?yàn)閏lass是引用類(lèi)型首妖,有可能有多個(gè)常量和變量在幕后同時(shí)引用同一個(gè)類(lèi)實(shí)例。(對(duì)于struct和enum來(lái)說(shuō)爷恳,這并不成立有缆。因?yàn)樗鼈冏鳛橹殿?lèi)型,在被賦予到常量温亲、變量或者傳遞到函數(shù)時(shí)棚壁,其值總是會(huì)被拷貝。)
如果能夠判定兩個(gè)常量或者變量是否引用同一個(gè)類(lèi)實(shí)例將會(huì)很有幫助栈虚。為了達(dá)到這個(gè)目的袖外,Swift 內(nèi)建了兩個(gè)恒等運(yùn)算符:
- 等價(jià)于(===)
- 不等價(jià)于(!==)
運(yùn)用這兩個(gè)運(yùn)算符檢測(cè)兩個(gè)常量或者變量是否引用同一個(gè)實(shí)例:
if tenEighty === alsoTenEighty {
print("tenEighty and alsoTenEighty refer to the same Resolution instance.")
}
//打印 "tenEighty and alsoTenEighty refer to the same Resolution instance."
注意,
等價(jià)于
(用三個(gè)=
表示)與等于
(用兩個(gè)=
表示)不同:
1.等價(jià)于
表示兩個(gè)類(lèi)類(lèi)型(class type)
的常量或者變量引用同一個(gè)類(lèi)實(shí)例魂务。
2.等于
表示兩個(gè)實(shí)例的值相等
或相同
曼验,判定時(shí)要遵照設(shè)計(jì)者定義的評(píng)判標(biāo)準(zhǔn),因此相對(duì)于相等
來(lái)說(shuō)粘姜,這是一種更加合適的叫法鬓照。