1. 類和結(jié)構(gòu)體對比
都能干的事兒:
- 定義屬性用來存儲值
- 定義方法用于提供功能
- 定義下標腳本用來允許使用下標語法訪問值
- 定義初始化器用于初始化狀態(tài)
- 可以被擴展來默認所沒有的功能
- 遵循協(xié)議來針對特定類型提供標準功能
類能干但結(jié)構(gòu)體不能干的事兒:
- 繼承允許一個類繼承另一個類的特征
- 類型轉(zhuǎn)換允許你在運行檢查和解釋一個類實例的類型
- 反初始化器允許一個類實例釋放任何其所被分配的資源
- 引用計數(shù)允許不止一個對類實例的引用
注意:
1.在Swift一個文件中定義一個類或者結(jié)構(gòu)體,系統(tǒng)自動生成面向其他代碼的外部接口抵碟。
2.結(jié)構(gòu)體在你的代碼中通過復制(淺拷貝)來傳遞,并不會使用引用計數(shù)。
語法:
class SomeClass {
// 類定義使用class關鍵字
}
struct SomeStructure {
// 結(jié)構(gòu)體定義使用struct關鍵字
}
舉個栗子:
struct Resolution {
var width = 0
var height = 0
}
class VideoMode {
var resolution = Resolution() // 變量resolution默認值為結(jié)構(gòu)體Resolution實例
var interlaced = false
var frameRate = 0.0
var name: String? // 變量name默認值為nil
}
上面定義僅僅描述了類或者結(jié)構(gòu)體的統(tǒng)一構(gòu)成耸序,但需要實例化才能在計算機內(nèi)存中生成具體的對象實例。簡單創(chuàng)建類和結(jié)構(gòu)體實例:
let someResolution = Resolution()
let someVideoMode = VideoMode()
// someResolution 和 someVideoMode 實例中的屬性為類和結(jié)構(gòu)體定義中的默認值
使用點語法來訪問屬性:
print("The width of someResolution is \(someResolution.width)")
// 結(jié)果為: "The width of someResolution is 0"
print("The width of someVideoMode is \(someVideoMode.resolution.width)")
// 結(jié)果為: "The width of someVideoMode is 0"
// 為屬性賦一個新值
someVideoMode.resolution.width = 1280
print("The width of someVideoMode is now \(someVideoMode.resolution.width)")
// 結(jié)果為: "The width of someVideoMode is now 1280"
注意: 不同于Objective-C鲁猩,Swift允許直接設置一個結(jié)構(gòu)體屬性中的子屬性坎怪。上述最后一個栗子中,
someVideoMode
的resolution
屬性中的width
這個屬性可以直接設置廓握,不用重新給resolution
屬性設置一個新值搅窿。
2. 結(jié)構(gòu)體和枚舉是值類型
Swift中所有的基本類型——整數(shù),浮點數(shù)隙券,布爾量男应,字符串,數(shù)組和字典——都是值類型娱仔,并且都以結(jié)構(gòu)體的形式在后臺實現(xiàn)沐飘。值類型賦值時直接采用原實例的拷貝,而非原實例牲迫。
舉個栗子:
let hd = Resolution(width: 1920, height: 1080) // 創(chuàng)建一個結(jié)構(gòu)體實例hd
var cinema = hd // 將實例的拷貝賦值給cinema
cinema.width = 2048 // 更改cinema中width屬性值
println("cinema is now \(cinema.width) pixels wide")
//結(jié)果為: "cinema is now 2048 pixels wide"
print("hd is still \(hd.width) pixels wide") // hd中的width屬性并不會受影響
// 結(jié)果為: "hd is still 1920 pixels wide"
3. 類是引用類型
引用類型賦值時耐朴,直接引用原實例對象,因此被賦值的任何變量都在更改唯一的一個實例盹憎。
舉個栗子:
// 創(chuàng)建一個VideoMode實例tenEighty并設置其屬性
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
// 將tenEighty對象賦值給alsoTenEighty
let alsoTenEighty = tenEighty
// 更改alsoTenEighty的frameRate屬性值為30.0
alsoTenEighty.frameRate = 30.0
// 發(fā)現(xiàn)筛峭,tenEighty的frameRate屬性值也變成了30.0.
print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
// 結(jié)果為: "The frameRate property of tenEighty is now 30.0"
// 結(jié)論: tenEighty 和 alsoTenEighty 指向同一個實例。
===
和 ==
運算符:
- "==" 對比兩邊的值是否相等
- "===" 對比兩邊的對象是否引用自同一個類的實例
4. 類和結(jié)構(gòu)體之間的選擇
結(jié)構(gòu)體實例總是通過值來傳遞陪每,而類實例總是通過引用來傳遞影晓。
何時采用結(jié)構(gòu)體:
- 結(jié)構(gòu)體的主要目的是為了封裝一些相關的簡單數(shù)據(jù)值
- 當你在賦予或者傳遞結(jié)構(gòu)實例時镰吵,有理由需要封裝的數(shù)據(jù)值被拷貝而不是引用
- 任何存儲在結(jié)構(gòu)體中的屬性是值類型,也將被拷貝而不是被引用
- 結(jié)構(gòu)體不需要從一個已存在類型繼承屬性或者行為
比如以下情況常用結(jié)構(gòu)體封裝:
- 幾何形狀的大小俯艰,可能封裝了一個
width
屬性和height
屬性捡遍,兩者都為double
類型 - 一定范圍的路徑,可能封裝了一個
start
屬性和length
屬性竹握,兩者為Int
類型 - 三維坐標系的一個點画株,可能封裝了
x
,y
和z
屬性,都是double
類型
在其他的情況下啦辐,定義一個類谓传,并創(chuàng)建這個類的實例,通過引用來管理和傳遞芹关。
事實上续挟,大部分的自定義的數(shù)據(jù)結(jié)構(gòu)應該是類,而不是結(jié)構(gòu)體侥衬。