最使人疲憊的往往不是道路的遙遠(yuǎn),而是你心中的郁悶;最使人頹廢的往往不是前途的坎坷,而是你自信的喪失;最使人痛苦的往往不是生活的不幸猿规,而是你希望的破滅;最使人絕望的往往不是挫折的打擊,而是心靈的死亡
前言
Swift語(yǔ)言同時(shí)支持類和結(jié)構(gòu)體兩種數(shù)據(jù)結(jié)構(gòu),類是面向?qū)ο缶幊讨蟹浅V匾囊粋€(gè)概念,而結(jié)構(gòu)體是從C語(yǔ)言中遺留下來(lái)的一種組合數(shù)據(jù)結(jié)構(gòu)窗悯。而Swift語(yǔ)言中結(jié)構(gòu)體的功能相對(duì)于C語(yǔ)言有了一定的提升,以至于在Swift語(yǔ)言中二者非常相似偷拔,常常令人難以取舍蒋院,今天我們就來(lái)揭示二者異同以及在實(shí)際開發(fā)中的取舍問(wèn)題。
相同點(diǎn)
在Swift語(yǔ)言中莲绰,結(jié)構(gòu)體和類都可以:
- 都可以定義方法欺旧,屬性
- 都能繼承或是實(shí)現(xiàn)某個(gè)協(xié)議
- 都有自己的初始化方法
- 都支持下標(biāo)訪問(wèn)語(yǔ)法
- 都支持?jǐn)U展
二者的定義方式是一樣的:
class A {
var p1:String?
var p2:String?
func f() {
print("這是類的定義")
}
}
struct A1 {
var p1:String?
var p2:String?
func f() {
print("這是結(jié)構(gòu)體的定義")
}
}
不同點(diǎn)
盡管有很多相似的地方,但類和結(jié)構(gòu)體還是有很多不同的地方蛤签,下面就讓筆者為你一一道來(lái)辞友!
- 類支持繼承
- 支持deInit()方法(C++語(yǔ)言中叫析構(gòu)函數(shù))釋放資源
- 引用計(jì)數(shù)器允許對(duì)一個(gè)類的多次引用
class B1 {
var x:Int?
var y:Int?
init() {
print("初始化方法,初始化時(shí)調(diào)用")
}
deinit {
print("反初始化方法,釋放資源時(shí)調(diào)用")
}
func f() {
print("B1->f()")
}
}
class B2 : B1 {
override func f() {
print("B2->f()")
}
}
let b1:B1 = B2()
b1.f()
struct B11 {
var x:Int?
var y:Int?
init() {
print("初始化方法,初始化時(shí)調(diào)用")
}
// 沒(méi)有deInit方法
// deinit {
//
// }
}
// 不支持繼承
//struct B12 : B11 {
//
//}
除了上面的不同點(diǎn)之外震肮,類和結(jié)構(gòu)體還有幾處很重要的不同點(diǎn):
- 編譯器為類自動(dòng)生成不帶參數(shù)的初始化方法称龙,而為結(jié)構(gòu)體生成帶所有屬性的初始化方法
- 結(jié)構(gòu)體實(shí)例是值類型,類實(shí)例是引用類型
// 編譯器為二者自動(dòng)生成初始化函數(shù)
class C1 {
var a:String?
var b:String?
}
struct C11 {
var a:String?
var b:String?
}
let c1:C1 = C1()
c1.a = "a"
let c11:C11 = C11(a: "a", b: "b")
// 類實(shí)例是引用類型
// 改變c2實(shí)例的值也會(huì)改變c1的值
let c2:C1 = c1
print("a=\(c1.a!)")
c2.a = "aaa"
print("a=\(c1.a!)")
// 結(jié)構(gòu)體實(shí)例是值類型
// 改變c22的值不會(huì)改變c11的值
var c22:C11 = c11
print("a=\(c11.a!)")
c22.a = "aaa"
print("a=\(c11.a!)")
下面戳晌,我們用一張表格來(lái)概括類和結(jié)構(gòu)體的不同:
不同點(diǎn) | 結(jié)構(gòu)體 | 類 |
---|---|---|
默認(rèn)初始化函數(shù) | 帶全部參數(shù) | 不帶參數(shù) |
實(shí)例類型 | 值類型 | 引用類型 |
繼承 | 不支持 | 支持 |
如何取舍
通過(guò)上面的分析鲫尊,我們可以知道,結(jié)構(gòu)體在設(shè)計(jì)上更偏向于數(shù)據(jù)的封裝沦偎。而類除了數(shù)據(jù)的封裝之外疫向,還偏向于針對(duì)數(shù)據(jù)的處理咳蔚。在類和結(jié)構(gòu)體不同點(diǎn)中,最重要的一點(diǎn)是:類實(shí)例是引用類型搔驼,而結(jié)構(gòu)體實(shí)例是值類型谈火,如果是數(shù)據(jù)的傳遞過(guò)程中,不希望影響原數(shù)據(jù)的值舌涨,請(qǐng)考慮結(jié)構(gòu)體糯耍,而如果本身考慮是對(duì)同一個(gè)實(shí)例進(jìn)行操作的話,則請(qǐng)考慮使用類囊嘉。還有一個(gè)非常重要的點(diǎn)是:結(jié)構(gòu)體不能實(shí)現(xiàn)繼承谍肤,多態(tài)等面向?qū)ο筇匦裕虼嘶┎绻紤]擴(kuò)展以及面向?qū)ο筇匦缘脑捇拇В舱?qǐng)使用類型。
概括來(lái)講:如果僅僅是針對(duì)數(shù)據(jù)的封裝的話焊刹,使用結(jié)構(gòu)體即可系任。而如果考慮運(yùn)行時(shí)特性以及類型的擴(kuò)展的話請(qǐng)使用類。
如果你喜歡我的這篇文章虐块,請(qǐng)點(diǎn)擊文章右上方的添加關(guān)注俩滥。如果你想和更多的人一起討論Swift語(yǔ)言,請(qǐng)加入我的Swift交流群贺奠,我們等著你霜旧。
也歡迎你fork這篇文章的源碼倉(cāng)庫(kù):https://github.com/yuanhoujun/Swift.git。更多的意見和討論請(qǐng)?jiān)谖恼孪路降脑u(píng)論里面告訴我