類和結(jié)構(gòu)體
可以通過使用常量、變量和函數(shù)完全相同的語法來定義屬性和方法向類和結(jié)構(gòu)添加功能。
Swift不需要為自定義類和結(jié)構(gòu)創(chuàng)建單獨的接口和實現(xiàn)文件,只需要在單個文件中定義一個類或結(jié)構(gòu)體Swift會自動形成對其他代碼可用的外部接口。
<br />
比較類和結(jié)構(gòu)體
類和結(jié)構(gòu)體的共同之處:
- 定義屬性以存儲值
- 定義方法以提供功能
- 定義下標使用下標語法提供對其值的訪問
- 定義初始化器以設(shè)置其初始狀態(tài)
- 擴展默認實現(xiàn)的功能
- 遵循協(xié)議以提供某種特定功能
類具有的附加功能:
- 繼承另一個類的特性
- 類型轉(zhuǎn)換使得在運行時檢查和解釋類實例的類型
- 析構(gòu)器以釋放其內(nèi)存
- 引用計數(shù)允許對類實例的多個引用
注意
結(jié)構(gòu)體是值類型,且沒有引用計數(shù),類是引用類型。
<br />
定義語法
類和結(jié)構(gòu)體定義語法類似,分別使用class和struct關(guān)鍵字。
class SomeClass {
// class definition goes here
}
struct SomeStructure {
// structure definition goes here
}
注意
類和結(jié)構(gòu)體的類型名采用首字母大寫的駝峰命名法,屬性和方法采用小寫的。
類和結(jié)構(gòu)體的定義示例:
struct Resolution {
var width = 0
var height = 0
}
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
類和結(jié)構(gòu)體的實例
類和結(jié)構(gòu)體創(chuàng)建實例的語法也非常相似:
let someResolution = Resolution()
let someVideoMode = VideoMode()
類和結(jié)構(gòu)體創(chuàng)建實例都使用初始化器,初始化器的最簡單形式是使用類或結(jié)構(gòu)體的類型名,后跟空括號。這樣會將所有屬性初始化為默認值。
訪問屬性
使用點語法訪問實例的屬性。
print("The width of someResolution is \(someResolution.width)")
// Prints "The width of someResolution is 0"
Swift可以直接設(shè)置結(jié)構(gòu)屬性的子屬性:
print("The width of someVideoMode is \(someVideoMode.resolution.width)")
// Prints "The width of someVideoMode is 0"
使用點語法給變量屬性設(shè)置新值:
someVideoMode.resolution.width = 1280
print("The width of someVideoMode is now \(someVideoMode.resolution.width)")
// Prints "The width of someVideoMode is now 1280"
結(jié)構(gòu)體類型的成員初始化器
所有結(jié)構(gòu)體會自動生成一個成員初始化器,通過名稱將實例的屬性的初始化值傳遞給成員初始化器:
let vga = Resolution(width: 640, height: 480)
而類結(jié)構(gòu)不生成默認的成員初始化器。
<br />
結(jié)構(gòu)體和枚舉是值類型
值類型是將值分配給變量或常量或?qū)⑵鋫鬟f給函數(shù)時復(fù)制其值的類型,改變其中一個而不會影響另一個。
Swift中的所有基本數(shù)據(jù)類型都是值類型,包括結(jié)構(gòu)體和枚舉。
說明結(jié)構(gòu)體是值類型的示例:
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
cinema.width = 2048
print("cinema is now \(cinema.width) pixels wide")
// Prints "cinema is now 2048 pixels wide"
print("hd is still \(hd.width) pixels wide")
// Prints "hd is still 1920 pixels wide"
說明枚舉是值類型的示例:
enum CompassPoint {
case north, south, east, west
}
var currentDirection = CompassPoint.west
let rememberedDirection = currentDirection
currentDirection = .east
if rememberedDirection == .west {
print("The remembered direction is still .west")
}
// Prints "The remembered direction is still .west"
<br />
類是引用類型
當引用類型被分配給變量或常量或?qū)⑵鋫鬟f給函數(shù)時,不會復(fù)制引用類型,而是直接使用原實例的引用,這意味著修改其中一個值會直接反映到另一個值。
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
// Prints "The frameRate property of tenEighty is now 30.0"
上述的類實例都分配給了常量,修改實例的屬性對常量本身的值無影響,只是改變內(nèi)部的屬性,未修改其引用。
等于運算符
使用等于運算符判斷兩個常量或變量是否為相同的類實例,即同一個引用,有兩個相等運算符:
- 想等 (===)
- 不想等 (!==)
`
if tenEighty === alsoTenEighty {
print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")
}
// Prints "tenEighty and alsoTenEighty refer to the same VideoMode instance."
指針
C和Objective-C語言中使用指針來引用內(nèi)存地址,而Swift中引用某個引用類型的實例與指針類似,但不是直接指向內(nèi)存地址的指針,創(chuàng)建引用也不需要使用星號(*)。
<br />
選擇類與結(jié)構(gòu)體
使用類和結(jié)構(gòu)體來定義復(fù)雜的自定義數(shù)據(jù)類型。
值類型和引用類型意味著結(jié)構(gòu)體和類適合于不同類型的任務(wù),依據(jù)以下原則考慮將一個數(shù)據(jù)類型定義為一個結(jié)構(gòu)體:
- 結(jié)構(gòu)體的主要目的是封裝一些相對簡單的數(shù)據(jù)值。
- 在分配或傳遞該實例時,期望封裝的值將被復(fù)制會更加合理,而不是引用。
- 由結(jié)構(gòu)體存儲的任何屬性本身都是值類型,也將被復(fù)制。
- 結(jié)構(gòu)體不需要從另一個現(xiàn)有類型繼承屬性或方法。
以下為使用結(jié)構(gòu)體的一些好的例子:
- 幾何形狀的大小,封裝了均為Double類型的width屬性和height屬性。
- 代表一系列值的范圍,封裝了均為Int類型的start屬性和length屬性。
- 3D坐標系統(tǒng)的一個點,封裝了均為Double類型的x,y和z屬性。
以上原則說明,
在所有其他條件下,定義為一個類,并創(chuàng)建要通過引用進行管理和傳遞的類的實例。,這意味著大多數(shù)自定義數(shù)據(jù)結(jié)構(gòu)應(yīng)該是類而不是結(jié)構(gòu)。