在Swift中,類是引用類型,引用類型在賦值和傳參時都是操作的引用,這些引用指向同一個對象。如下,對classA的修改也會影響到classB:
classTestClass{
var str = "my class"
}
let classA =TestClass()
let classB =classA
classA.str="your class"
print(classB.str) //your class
但是有時候我們需要獲取一個對象的拷貝,而不是引用,如在自定義結(jié)構(gòu)體中含有引用類型屬性時實現(xiàn)寫時復(fù)制,就需要對該引用屬性進(jìn)行對象拷貝,參見《Swift結(jié)構(gòu)體內(nèi)存寫時復(fù)制》。那么在Swift中如何實現(xiàn)對象拷貝?
有兩種方法:
- 繼承自NSObject,遵守NSCopying協(xié)議,在Foundation框架內(nèi)
- 自定義一個Copyable協(xié)議,用一個純Swift類去遵守這個協(xié)議
本文只討論后一種實現(xiàn),我們先給出一種實現(xiàn)方式
protocol Copyable {
func copy() -> Copyable
}
class MyClass:Copyable{
var des = ""
func copy()-> Copyable{
return MyClass(self.des)
}
required init(_ des:String){
self.des = des
}
}
let myClass = MyClass("my class")
let yourClass = myClass.copy() as! MyClass
yourClass.des = "your class"
print(yourClass.des)//your class
print(myClass.des)// my class
我們可以看到修改yourClass的屬性沒有影響到myClass的屬性,說明成功實現(xiàn)了對象拷貝。但是類可以繼承的,子類也會持有父類的拷貝方,此時就會出現(xiàn)拷貝得到的新對象類型問題,如下我們得到的sonB為Copyable類型(Swift中,沒有用到Self并且沒有用到關(guān)聯(lián)類型的協(xié)議可以作為獨立的類型使用。),并且無法轉(zhuǎn)化為Son類型,因為copy方法為我返回的是一個MyClass對象,不能向下轉(zhuǎn)型。
class Son:MyClass{
}
let sonA = Son("sonA")
let sonB = sonA.copy() //Copyable
我們做一些修改來使拷貝功能對子類有效
protocol Copyable {
func copy()-> Self
}
class MyClass:Copyable{
var des = " "
func copy() -> Self{
let obj = self.dynamicType.init(self.des)
return obj
}
required init(_ des:String){
self.des = des
}
}
let myClass = MyClass("my class")
let yourClass = myClass.copy()
yourClass.des = "your class"
print(yourClass.des)//your class
print(myClass.des)// my class
class Son:MyClass{
}
let sonA = Son("sonA")
let sonB = sonA.copy()
sonB.des = "sonB"
print(sonA.des)//sonA
print(sonB.des)//sonB
從結(jié)果來看,我們已經(jīng)成功實現(xiàn)了子類的拷貝方法。我們在Copyable協(xié)議中返回了一個Self,之前提到過出現(xiàn)過Self的協(xié)議不能作為獨立類型使用,而只能作為泛型約束。Self指的就是實現(xiàn)這個協(xié)議本身的類型,在這種情況下Self還包括了這個類型的子類。所以我么甚至不需要類型轉(zhuǎn)換,就得到了sonA的拷貝sonB。