Swift-類和結構體

類和結構體是通用的,靈活的結構,成為程序代碼的基礎。 您可以通過使用與常量,變量和函數完全相同的語法來定義屬性和方法來向類和結構添加功能。

與其他編程語言不同,Swift不需要為自定義類和結構創建單獨的接口和實現文件。 在Swift中,您可以在單個文件中定義一個類或結構,并且該類或結構的外部接口自動可供其他代碼使用。

類的實例傳統上稱為對象。 但是,Swift類和結構在功能上比其他語言更接近,本章的很多內容描述了可應用于類或結構類型實例的功能。 因此,使用更一般的術語實例。

類和結構體的比較

Swift中的類和結構有很多共同點。 兩者都可以:

  • 定義要存儲值的屬性
  • 定義方法以提供功能
  • 定義下標,以使用下標語法訪問其值
  • 定義初始化程序以設置其初始狀態
  • 擴展其功能超出默認實現
  • 符合協議以提供某種類型的標準功能

有關更多信息,請參閱屬性,方法,下標,初始化,擴展和協議。
類具有結構不具有的附加功能:
繼承使一個類能夠繼承另一個類的特性。

  • 類型轉換使您能夠在運行時檢查和解釋類實例的類型。
  • Deinitializers使一個類的實例釋放它分配的任何資源。
  • 引用計數允許對類實例的多個引用。

有關更多信息,請參閱繼承,類型轉換,取消初始化和自動引用計數。

語法定義

類和結構體具有類似的語法定義,引入一個類的class關鍵字和一個結構體的struct關鍵字,兩者都將整個定義放在一個花括號內

class SomeClass {
    // class definition goes here
}
struct SomeStructure {
    // structure definition goes here
}

這里有一個結構定義和類定義的例子:

struct Resolution {
    var width = 0
    var height = 0
}
class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}

類和結構體的實例

Resolution結構定義和VideoMode類定義僅描述Resolution或VideoMode的外觀。 他們自己沒有描述特定的Resolution或VideoMode。 為此,您需要創建結構或類的實例。

對于結構和類,創建實例的語法非常相似:

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

結構和類都對新實例使用初始化語法。 初始化語法的最簡單形式使用類或結構的類型名稱,后跟空括號,例如Resolution()或VideoMode()。 這將創建一個類或結構的新實例,并將任何屬性初始化為其默認值。 類和結構初始化在初始化中有更詳細的描述。

訪問屬性

您可以使用點語法訪問實例的屬性。 在點語法中,您在實例名稱后立即寫入屬性名稱,以句點(.)分隔,不帶任何空格:

print("The width of someResolution is \(someResolution.width)")
// Prints "The width of someResolution is 0"

翻譯關閉即時翻譯

在本例中,someResolution.width指的是someResolution的width屬性,并返回其默認初始值0。

您可以深入查看子屬性,例如VideoMode的resolution屬性中的width屬性:

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

您還可以使用點語法為變量屬性分配新值:

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

注意:
與Objective-C不同,Swift允許您直接設置結構屬性的子屬性。 在上面的最后一個例子中,someVideoMode的resolution屬性的width屬性是直接設置的,而不需要將整個resolution屬性設置為一個新值。

結構體類型的成員初始化器

所有結構都具有自動生成的成員初始化器,您可以使用它來初始化新結構實例的成員屬性。 新實例的屬性的初始值可以按名稱傳遞到成員初始化程序:

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

與結構不同,類實例不接收默認的成員初始化。 在初始化中更詳細地描述初始化器。

結構和枚舉是值類型

值類型是一種類型,當它被賦值給一個變量或常量,或者當它被傳遞給一個函數時,它的值被復制。

事實上,Swift整數,浮點數,布爾值,字符串,數組和字典中的所有基本類型都是值類型,并且作為幕后結構實現。

所有結構和枚舉都是Swift中的值類型。 這意味著,您創建的任何結構和枚舉實例(以及它們作為屬性的任何值類型)在您的代碼中傳遞時總是被復制。

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"

當給予cinema當前值hd時,存儲在hd中的值被復制到新的cinema實例中。 最終結果是兩個完全獨立的實例,剛剛發生包含相同的數值。 因為它們是單獨的實例,將cinema設置為2048不會影響存儲在hd中的寬度。

同樣的行為適用于枚舉:

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"

當rememberedDirection被賦值為currentDirection的值時,它實際上被設置為該值的副本。 之后更改currentDirection的值不會影響存儲在rememberedDirection中的原始值的副本。

類是引用類型

與值類型不同,引用類型在分配給變量或常量時或者傳遞給函數時不會被復制。 也不是副本,而是使用對同一現有實例的引用。

這里有一個例子,使用上面定義的VideoMode類:

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"

注意,tenEighty和TenEighty被聲明為常量,而不是變量。 但是,您仍然可以更改tenEighty.frameRate和TenEighty.frameRate,因為tenEighty和AlsoTenEighty常量本身的值實際上不會更改。 tenEighty和TenEighty自己不會“存儲”VideoMode實例,而是它們都指向幕后的VideoMode實例。 它是底層VideoMode的frameRate屬性更改,而不是該VideoMode的常量引用的值。

身份操作符

因為類是引用類型,所以有可能多個常量和變量在后臺引用一個類的同一個單一實例。 (對于結構和枚舉不是這樣,因為它們在分配給常量或變量或傳遞給函數時總是被復制。)

有時可能有用的是找出兩個常量或變量是否指向一個類的完全相同的實例。 為了實現這一點,Swift提供了兩個身份操作符:

  • 相同(===)
  • 不同于(!==)

使用這些運算符來檢查兩個常量或變量是否引用同一個單個實例:

if tenEighty === alsoTenEighty {
    print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")
}
// Prints "tenEighty and alsoTenEighty refer to the same VideoMode instance."

"=="和"==="的意義是不相同的

  • “與之相同”意味著類類型的兩個常量或變量引用完全相同的類實例。
  • “等于”是指兩個實例在值上被認為是“等于”或“等效”,對于類型的設計者定義的一些適當的“等于”含義。

當您定義自己的自定義類和結構時,您有責任決定什么是“等于”的兩個實例。 在等價運算符中描述了定義自己的“等于”和“不等于”運算符的實現的過程。

指針

如果你有C,C ++或Objective-C的經驗,你可能知道這些語言使用指針來引用內存中的地址。 引用某個引用類型的實例的Swift常量或變量類似于C中的指針,但不是直接指向內存中地址的指針,并且不要求您寫入星號(*)以指示您 正在創建一個引用。 相反,這些引用的定義與Swift中的任何其他常量或變量一樣。

在類和結構之間選擇

作為一般準則,考慮在以下一個或多個條件適用時創建結構體:

  • 該結構的主要目的是封裝一些相對簡單的數據值。
  • 當您分配或傳遞該結構的實例時,期望封裝的值將被復制而不是被引用是合理的。
  • 由結構存儲的任何屬性都是值類型,這也將被期望被復制而不是被引用。
  • 該結構不需要從另一個現有類型繼承屬性或行為。

字符串,數組和字典的賦值和復制行為

在Swift中,許多基本數據類型,例如String,Array和Dictionary被實現為結構體。 這意味著,如果字符串,數組和字典等數據被分配給一個新的常量或變量,或者當它們傳遞給一個函數或方法時,它們就被復制。

這個行為不同于Foundation:NSString,NSArray和NSDictionary實現為類而不是結構。 Foundation中的字符串,數組和字典總是分配和傳遞作為對現有實例的引用,而不是作為副本。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,923評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,740評論 3 420
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,856評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,175評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,931評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,321評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,383評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,533評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,082評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,891評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,618評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,319評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,732評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,987評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,794評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,076評論 2 375

推薦閱讀更多精彩內容