Swift類是引用類型
類是引用類型
與值類型不同,引用類型在被賦予到一個變量,常量或者被傳遞到一個函數時,操作的並不是其拷貝。因此,引用的是已存在的實例本身而不是其拷貝。
請看下面這個示例,其使用了之前定義的VideoMode
類:
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
以上示例中,聲明瞭一個名爲tenEighty
的常量,其引用了一個VideoMode
類的新實例。在之前的示例中,這個視頻模式(video mode)被賦予了HD分辨率(1920*1080)的一個拷貝(hd
)。同時設置爲交錯(interlaced),命名爲「1080i」
。最後,其幀率是25.0
幀每秒。
然後,tenEighty
被賦予名爲alsoTenEighty
的新常量,同時對alsoTenEighty
的幀率進行修改:
let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
因爲類是引用類型,所以tenEight
和alsoTenEight
實際上引用的是相同的VideoMode
實例。換句話說,它們只是同一個實例的兩種叫法。
下面,通過查看tenEighty
的frameRate
屬性,我們會發現它正確的顯示了基本VideoMode
實例的新幀率,其值爲30.0
:
println("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
// 輸出 "The frameRate property of theEighty is now 30.0"
需要注意的是tenEighty
和alsoTenEighty
被聲明爲*常量((constants)*而不是變量。然而你依然可以改變tenEighty.frameRate
和alsoTenEighty.frameRate
,因爲這兩個常量本身不會改變。它們並不儲存
這個VideoMode
實例,在後臺僅僅是對VideoMode
實例的引用。所以,改變的是被引用的基礎VideoMode
的frameRate
參數,而不改變常量的值。
恆等運算符
因爲類是引用類型,有可能有多個常量和變量在後臺同時引用某一個類實例。(對於結構體和枚舉來說,這並不成立。因爲它們作值類型,在被賦予到常量,變量或者傳遞到函數時,總是會被拷貝。)
如果能夠判定兩個常量或者變量是否引用同一個類實例將會很有幫助。爲了達到這個目的,Swift 內建了兩個恆等運算符:
- 等價於 ( === )
- 不等價於 ( !== )
以下是運用這兩個運算符檢測兩個常量或者變量是否引用同一個實例:
if tenEighty === alsoTenTighty {
println("tenTighty and alsoTenEighty refer to the same Resolution instance.")
}
//輸出 "tenEighty and alsoTenEighty refer to the same Resolution instance."
請注意「等價於」(用三個等號表示,===) 與「等於」(用兩個等號表示,==)的不同:
- 「等價於」表示兩個類類型(class type)的常量或者變量引用同一個類實例。
- 「等於」表示兩個實例的值「相等」或「相同」,判定時要遵照類設計者定義定義的評判標準,因此相比於「相等」,這是一種更加合適的叫法。
當你在定義你的自定義類和結構體的時候,你有義務來決定判定兩個實例「相等」的標準。在章節運算符函數(Operator Functions)中將會詳細介紹實現自定義「等於」和「不等於」運算符的流程。
指針
如果你有 C,C++ 或者 Objective-C 語言的經驗,那麼你也許會知道這些語言使用指針來引用內存中的地址。一個 Swift 常量或者變量引用一個引用類型的實例與 C 語言中的指針類似,不同的是並不直接指向內存中的某個地址,而且也不要求你使用星號(*)來表明你在創建一個引用。Swift 中這些引用與其它的常量或變量的定義方式相同。