Swift語法之類和結(jié)構(gòu)體

類和結(jié)構(gòu)體是人們構(gòu)建代碼所用的一種通用且靈活的構(gòu)造體。我們可以使用完全相同的語法規(guī)則來為類和結(jié)構(gòu)體定義屬性(常量、變量)和添加方法,從而擴(kuò)展類和結(jié)構(gòu)體的功能。

與其他編程語言所不同的是,Swift 并不要求你為自定義類和結(jié)構(gòu)去創(chuàng)建獨(dú)立的接口和實(shí)現(xiàn)文件。你所要做的是在一個單一文件中定義一個類或者結(jié)構(gòu)體,系統(tǒng)將會自動生成面向其它代碼的外部接口。

類和結(jié)構(gòu)體對比

Swift 中類和結(jié)構(gòu)體有很多共同點(diǎn)。共同處在于:

  • 定義屬性用于存儲值
  • 定義方法用于提供功能
  • 定義下標(biāo)操作通過下標(biāo)語法可以訪問它們的值
  • 定義構(gòu)造器用于生成初始化值
  • 通過擴(kuò)展以增加默認(rèn)實(shí)現(xiàn)的功能
  • 遵循協(xié)議以提供某種標(biāo)準(zhǔn)功能

與結(jié)構(gòu)體相比,類還有如下的附加功能:

  • 繼承允許一個類繼承另一個類的特征
  • 類型轉(zhuǎn)換允許在運(yùn)行時(shí)檢查和解釋一個類實(shí)例的類型
  • 析構(gòu)器允許一個類實(shí)例釋放任何其所被分配的資源
  • 引用計(jì)數(shù)允許對一個類的多次引用

類和結(jié)構(gòu)體有著類似的定義方式。我們通過關(guān)鍵字 class 和 struct 來分別表示類和結(jié)構(gòu)體,并在一對大括號中定義它們的具體內(nèi)容:

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)體和類實(shí)例的語法非常相似:

let someResolution = Resolution()
let someVideoMode = VideoMode()

通過使用點(diǎn)語法,你可以訪問實(shí)例的屬性。其語法規(guī)則是,實(shí)例名后面緊跟屬性名,兩者通過點(diǎn)號(.)連接:

print("The width of someResolution is \(someResolution.width)")

你也可以訪問子屬性,如 VideoMode 中 Resolution 屬性的 width 屬性:

print("The width of someVideoMode is \(someVideoMode.resolution.width)")

你也可以使用點(diǎn)語法為變量屬性賦值,Swift 允許直接設(shè)置結(jié)構(gòu)體屬性的子屬性:

someVideoMode.resolution.width = 1280
print("The width of someVideoMode is now \(someVideoMode.resolution.width)")

所有結(jié)構(gòu)體都有一個自動生成的成員逐一構(gòu)造器,用于初始化新結(jié)構(gòu)體實(shí)例中成員的屬性。新實(shí)例中各個屬性的初始值可以通過屬性的名稱傳遞到成員逐一構(gòu)造器之中:

let vga = Resolution(width: 640, height: 480)

在 Swift 中,所有的結(jié)構(gòu)體和枚舉類型都是值類型。這意味著它們的實(shí)例,以及實(shí)例中所包含的任何值類型屬性,在代碼中傳遞的時(shí)候都會被復(fù)制。

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd

下面,為了符合數(shù)碼影院放映的需求(2048 像素寬,1080 像素高),cinema 的 width 屬性需要作如下修改:

cinema.width = 2048

這里,將會顯示 cinema 的 width 屬性確已改為了 2048:

print("cinema is now  \(cinema.width) pixels wide")

然而,初始的 hd 實(shí)例中 width 屬性還是 1920:

print("hd is still \(hd.width) pixels wide")

枚舉也遵循相同的行為準(zhǔn)則:

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")
}
// 打印 "The remembered direction is still .West"

類是引用類型

與值類型不同,引用類型在被賦予到一個變量、常量或者被傳遞到一個函數(shù)時(shí),其值不會被拷貝。因此,引用的是已存在的實(shí)例本身而不是其拷貝。

請看下面這個示例,其使用了之前定義的 VideoMode 類:

let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0

然后,tenEighty 被賦予名為 alsoTenEighty 的新常量,同時(shí)對 alsoTenEighty 的幀率進(jìn)行修改:

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0

因?yàn)轭愂且妙愋?,所?tenEight 和 alsoTenEight 實(shí)際上引用的是相同的 VideoMode 實(shí)例

print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
// 打印 "The frameRate property of theEighty is now 30.0"

因?yàn)轭愂且妙愋停锌赡苡卸鄠€常量和變量在幕后同時(shí)引用同一個類實(shí)例。如果能夠判定兩個常量或者變量是否引用同一個類實(shí)例將會很有幫助。為了達(dá)到這個目的,Swift 內(nèi)建了兩個恒等運(yùn)算符:

  • 等價(jià)于(===)
  • 不等價(jià)于(!==)
    運(yùn)用這兩個運(yùn)算符檢測兩個常量或者變量是否引用同一個實(shí)例:
if tenEighty === alsoTenEighty {
    print("tenEighty and alsoTenEighty refer to the same Resolution instance.")
}

什么時(shí)候選擇使用結(jié)構(gòu)體:
按照通用的準(zhǔn)則,當(dāng)符合一條或多條以下條件時(shí),請考慮構(gòu)建結(jié)構(gòu)體:

  • 該數(shù)據(jù)結(jié)構(gòu)的主要目的是用來封裝少量相關(guān)簡單數(shù)據(jù)值。
  • 有理由預(yù)計(jì)該數(shù)據(jù)結(jié)構(gòu)的實(shí)例在被賦值或傳遞時(shí),封裝的數(shù)據(jù)將會被- 拷貝而不是被引用。
  • 該數(shù)據(jù)結(jié)構(gòu)中儲存的值類型屬性,也應(yīng)該被拷貝,而不是被引用。
  • 該數(shù)據(jù)結(jié)構(gòu)不需要去繼承另一個既有類型的屬性或者行為。

字符串、數(shù)組、和字典類型的賦值與復(fù)制行為

Swift 中,許多基本類型,諸如 String,Array 和 Dictionary 類型均以結(jié)構(gòu)體的形式實(shí)現(xiàn)。這意味著被賦值給新的常量或變量,或者被傳入函數(shù)或方法中時(shí),它們的值會被拷貝。

Objective-C 中 NSString,NSArray 和 NSDictionary 類型均以類的形式實(shí)現(xiàn),而并非結(jié)構(gòu)體。它們在被賦值或者被傳入函數(shù)或方法時(shí),不會發(fā)生值拷貝,而是傳遞現(xiàn)有實(shí)例的引用。

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

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

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