Swift 中的值類型與引用類型(Value and Reference Types )

Swift 類型分為兩種:值類型與引用類型。
值類型:每個實例擁有獨一無二的數(shù)據(jù)拷貝,例如基礎(chǔ)數(shù)據(jù)類型(Int、Float、Double等)、String、集合類型(Dictionary、Set、Array)、元組、枚舉、結(jié)構(gòu)體等。
引用類型:每個實例共享唯一一份數(shù)據(jù)拷貝,一般以類(Class)形式出現(xiàn)。

區(qū)別

值類型與引用類型最基本的區(qū)別就是拷貝之后的結(jié)果,值類型被拷貝的時候,相當(dāng)于建立一個新的獨立的實例,這個實例擁有自己的獨有的數(shù)據(jù)且不受其他實例的數(shù)據(jù)變化影響。也可以說拷貝在賦值、初始化、傳遞參數(shù)等過程中的數(shù)據(jù)并為數(shù)據(jù)創(chuàng)建一個獨立的實例。

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

拷貝一個引用類型的時候,本質(zhì)上是創(chuàng)建一個共享的實例的副本,兩者共用一套數(shù)據(jù)。在拷貝后,兩個實例指向了同一份數(shù)據(jù),所以修改其一的數(shù)據(jù),另一個實例隨之改變。

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

可變在安全性中的角色

使用值類型可以不用擔(dān)心在某個地方對數(shù)據(jù)的修改而影響到其他地方的數(shù)據(jù)。在多線程環(huán)境中非常有用,因為不同的線程有可能會在不知情的情況下改變數(shù)據(jù)。發(fā)生這種Bug后,調(diào)試就非常困難。

因為值類型和引用類型的區(qū)別就在于當(dāng)你修改類型實例的數(shù)據(jù)時,它們對原始類型數(shù)據(jù)的處理方式不同。但是有一種情況,值類型和引用類型的處理方式卻又相似,那就是當(dāng)類型實例的數(shù)據(jù)為只讀的時候。在不存在修改的情況下,值類型和引用類型就沒什么區(qū)別了。

在Swift中可以通過定義不可改變的存儲屬性來創(chuàng)建一個不可變的類,避免暴露出的API被修改。許多普通的Cocoa框架里的類,如NSURL,都被設(shè)計成不可變的類。

類型選擇

創(chuàng)建一個新類型的時候,如何選擇值類型還是引用類型呢?在使用Cocoa框架時,很多API都是NSObject的子類,那么就必須要使用引用類型,也就是類class。其他情況下,參考如下:

使用值類型的情景:
?使用==運算符比較實例數(shù)據(jù)時。
?單獨復(fù)制一份實例數(shù)據(jù)時。
?在多線程環(huán)境下操作數(shù)據(jù)時。

使用引用類型(比如class)的情景:
?當(dāng)使用===運算符判斷兩個對象是否引用同一個實例時。
?需要創(chuàng)建一個共享的、可變的對象時。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容