Swift 類(lèi)型分為兩種:值類(lèi)型與引用類(lèi)型。
值類(lèi)型:每個(gè)實(shí)例擁有獨(dú)一無(wú)二的數(shù)據(jù)拷貝,例如基礎(chǔ)數(shù)據(jù)類(lèi)型(Int、Float、Double等)、String、集合類(lèi)型(Dictionary、Set、Array)、元組、枚舉、結(jié)構(gòu)體等。
引用類(lèi)型:每個(gè)實(shí)例共享唯一一份數(shù)據(jù)拷貝,一般以類(lèi)(Class)形式出現(xiàn)。
區(qū)別
值類(lèi)型與引用類(lèi)型最基本的區(qū)別就是拷貝之后的結(jié)果,值類(lèi)型被拷貝的時(shí)候,相當(dāng)于建立一個(gè)新的獨(dú)立的實(shí)例,這個(gè)實(shí)例擁有自己的獨(dú)有的數(shù)據(jù)且不受其他實(shí)例的數(shù)據(jù)變化影響。也可以說(shuō)拷貝在賦值、初始化、傳遞參數(shù)等過(guò)程中的數(shù)據(jù)并為數(shù)據(jù)創(chuàng)建一個(gè)獨(dú)立的實(shí)例。
struct Person{
var name: String?
init(name:String?) {
self.name = name
}
}
var p1 = Person.init(name: "hehe")
var p2 = p1 //p2是p1的拷貝
p2.name = "haha" //修改p2的數(shù)據(jù),p1并不被受影響
print(p1.name!,p2.name!)
//打印:hehe haha
拷貝一個(gè)引用類(lèi)型的時(shí)候,本質(zhì)上是創(chuàng)建一個(gè)共享的實(shí)例的副本,兩者共用一套數(shù)據(jù)。在拷貝后,兩個(gè)實(shí)例指向了同一份數(shù)據(jù),所以修改其一的數(shù)據(jù),另一個(gè)實(shí)例隨之改變。
class Person{
var name: String?
init(name:String?) {
self.name = name
}
}
var p1 = Person.init(name: "hehe")
var p2 = p1 //p2是p1的拷貝
p2.name = "haha" //修改p2的數(shù)據(jù),p1的數(shù)據(jù)隨之改變,p1/p2共用一套數(shù)據(jù)
print(p1.name!,p2.name!)
//打印:haha haha
可變?cè)诎踩灾械慕巧?/h1>
使用值類(lèi)型可以不用擔(dān)心在某個(gè)地方對(duì)數(shù)據(jù)的修改而影響到其他地方的數(shù)據(jù)。在多線程環(huán)境中非常有用,因?yàn)椴煌木€程有可能會(huì)在不知情的情況下改變數(shù)據(jù)。發(fā)生這種Bug后,調(diào)試就非常困難。
因?yàn)橹殿?lèi)型和引用類(lèi)型的區(qū)別就在于當(dāng)你修改類(lèi)型實(shí)例的數(shù)據(jù)時(shí),它們對(duì)原始類(lèi)型數(shù)據(jù)的處理方式不同。但是有一種情況,值類(lèi)型和引用類(lèi)型的處理方式卻又相似,那就是當(dāng)類(lèi)型實(shí)例的數(shù)據(jù)為只讀的時(shí)候。在不存在修改的情況下,值類(lèi)型和引用類(lèi)型就沒(méi)什么區(qū)別了。
在Swift中可以通過(guò)定義不可改變的存儲(chǔ)屬性來(lái)創(chuàng)建一個(gè)不可變的類(lèi),避免暴露出的API被修改。許多普通的Cocoa框架里的類(lèi),如NSURL,都被設(shè)計(jì)成不可變的類(lèi)。
類(lèi)型選擇
創(chuàng)建一個(gè)新類(lèi)型的時(shí)候,如何選擇值類(lèi)型還是引用類(lèi)型呢?在使用Cocoa框架時(shí),很多API都是NSObject的子類(lèi),那么就必須要使用引用類(lèi)型,也就是類(lèi)class。其他情況下,參考如下:
使用值類(lèi)型的情景:
?使用==運(yùn)算符比較實(shí)例數(shù)據(jù)時(shí)。
?單獨(dú)復(fù)制一份實(shí)例數(shù)據(jù)時(shí)。
?在多線程環(huán)境下操作數(shù)據(jù)時(shí)。
使用引用類(lèi)型(比如class)的情景:
?當(dāng)使用===運(yùn)算符判斷兩個(gè)對(duì)象是否引用同一個(gè)實(shí)例時(shí)。
?需要?jiǎng)?chuàng)建一個(gè)共享的、可變的對(duì)象時(shí)。