swift簡單總結(十九)—— 類和結構體

版本記錄

版本號 時間
V1.0 2017.07.28

前言

??我是swift2.0的時候開始接觸的,記得那時候還不是很穩定,公司的項目也都是用oc做的,并不對swift很重視,我自己學了一段時間,到現在swift3.0+已經出來了,自己平時也不寫,忘記的也差不多了,正好項目這段時間已經上線了,不是很忙,我就可以每天總結一點了,希望對自己對大家有所幫助。在總結的時候我會對比oc進行說明,有代碼的我會給出相關比對代碼。
1. swift簡單總結(一)—— 數據簡單值和類型轉換
2. swift簡單總結(二)—— 簡單值和控制流
3. swift簡單總結(三)—— 循環控制和函數
4. swift簡單總結(四)—— 函數和類
5. swift簡單總結(五)—— 枚舉和結構體
6. swift簡單總結(六)—— 協議擴展與泛型
7. swift簡單總結(七)—— 數據類型
8. swift簡單總結(八)—— 別名、布爾值與元組
9. swift簡單總結(九)—— 可選值和斷言
10. swift簡單總結(十)—— 運算符
11. swift簡單總結(十一)—— 字符串和字符
12. swift簡單總結(十二)—— 集合類型之數組
13. swift簡單總結(十三)—— 集合類型之字典
14. swift簡單總結(十四)—— 控制流
15. swift簡單總結(十五)—— 控制轉移語句
16. swift簡單總結(十六)—— 函數
17. swift簡單總結(十七)—— 閉包(Closures)
18. swift簡單總結(十八)—— 枚舉

類和結構體

??類和結構體是人們構建代碼所用的一種通用且靈活的構造體。與其他編程語言不同的是,swift并不要求你為自定義類和結構體去創建獨立的接口和實現文件,你需要做的就是在一個單一文件中定義一個類或者結構體,系統將會自動生成面向其他代碼的外部接口。

下面將從下面幾個方向進行講述

  • 類和結構體對比
  • 結構體和枚舉是值類型
  • 類是引用類型
  • 類和結構體的選擇
  • 集合collection類型的賦值和復制行為

類和結構體對比

1. 類和結構體的對比

swift中類和結構體有很多共同點,主要是:

  • 定義屬性用于存儲值
  • 定義方法用于提供功能
  • 定義附屬腳本用于訪問值
  • 定義構造器用于生成初始化值
  • 通過擴展以增加默認實現的功能
  • 符合協議以對某類提供標準功能

與結構體相比,類還有如下的功能:

  • 繼承允許一個類繼承另一個類的特征
  • 類型轉換允許在運行時檢查和解釋一個類實例的類型
  • 解構器允許一個類實例釋放任何其所被分配的資源
  • 引用計數允許對一個類的多次引用

注意:結構體總是通過被復制的方式在代碼中傳遞,因此,請不要使用引用計數。

2. 定義

??下面我們看一下類和結構體是如何定義的,習慣上類名和結構體名是以大寫字母開頭,屬性和方法是以小寫字母開頭,這復合swift的習慣。

下面看一下具體的定義。


class SomeClass {
    //class definition goes here
}

struct SomeStruct {
    //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?
}

3. 類和結構體實例

??可以用下邊方式進行實例化,結構體和類都使用構造器語法來生成新的實例,構造器語法的最簡單形式是在結構體或者類的類型名稱后跟隨一個空括號。

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

4. 屬性訪問

??可以使用點語法,你可以訪問實例中所包含的屬性,語法規則是:實例名稱緊跟屬性名。

    let someResolution = Resolution()
    let someVideoMode = VideoMode()
    print(someResolution.width)
    print(someVideoMode.resolution.width)

你可以使用點語法為屬性變量賦值。

someVideoMode.resolution.width = 100

??大家可以看點,swift允許使用點語法直接給一個屬性賦值,這個比OC要靈活的多了,大家估計還記得OCframe,不可以直接改變其中的成員,要找一個中間變量,改變中間變量的成員,修改以后在賦值回去才可以。這一點swift要靈活的多了。

5. 結構體類型的成員逐一構造器 - Memberwise Initializers for structure Types

??所有結構體都有一個自動生成的成員逐一構造器,用于初始化新結構體實例中成員的屬性,新實例中各個屬性的初始值可以通過屬性的名稱傳遞到成員逐一構造器中,下面看代碼。

let resolution = Resolution(width: 1920, height: 1080)

與結構體不同,類實例沒有默認的成員逐一構造器。


結構體和枚舉是值類型

??值類型被賦予給一個變量,常數或者本身被傳遞給一個函數的時候,實際上操作的是其的拷貝。其實,在swift中,所有基本類型:整數、浮點數、布爾值、字符值、數組和字典,都是值類型,并且都是以結構體的形式在后臺所實現。在swift中,所有的結構體和枚舉都是值類型,這意味著他們的實例,以及實例中所包含的任何值類型屬性,在代碼中傳遞的時候都會被復制。

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

??在上面的例子中,聲明一個常量resolution并給一個初始值,然后又定義了名字為cinema的變量,其值為之前聲明的resolution,因為Resolution是一個結構體,所以cinema的值其實是resolution的一個拷貝副本,而不是resolution本身,盡管resolutioncinema有著相同的寬和高,但是在后臺中,它們是兩個完全不同的實例。

下面看這個例子

class JJSwiftVC: UIViewController
{
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.lightGray
        
        let resolution = Resolution(width: 1920, height: 1080)
        var cinema = resolution
        cinema.width = 2080
        print("cinema = \(cinema)")
        print("resolution = \(resolution)")
    }
}

下面看輸出結果

cinema = Resolution(width: 2080, height: 1080)
resolution = Resolution(width: 1920, height: 1080)

??進一步證明了結構體是值類型,在將resolution賦值給cinema的時候,實際上是將resolution中所存儲的值進行拷貝,然后將拷貝的數據存儲到新的cinema中,結果是兩個完全獨立的實例碰巧包含有相同的數值。修改其中一個的值,不會影響另外一個的值。

枚舉也遵循相同的準則

class JJSwiftVC: UIViewController
{
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.lightGray
        
        var currentDirection = CompassPort.West
        let lastDirection = currentDirection
        currentDirection = .East
        if lastDirection == .West {
            print("The remember direction is still .West")
        }
        else {
            print("The remember direction is still .East")
        }
    }
}

下面看輸出結果

The remember direction is still .West

說明枚舉也是值類型。


類是引用類型

??與值類型不同,引用類型在被賦予到一個變量、常量或者被傳遞到一個函數時,操作的是引用,并不是拷貝,因此,引用的是已知存在的實例本身而不是拷貝。

class JJSwiftVC: UIViewController
{
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.lightGray
        
        let resolution = Resolution()
        let mode = VideoMode()
        mode.resolution = resolution
        mode.interlaced = false
        mode.name = "10086"
        mode.frameRate = 25.0
        
        let nextMode = mode
        nextMode.frameRate = 30.0
        print(mode.frameRate)
        print(nextMode.frameRate)
    }
}

下面看輸出結果

30.0
30.0

??可見,類是引用類型。還需要注意的是modenextMode被聲明為常量,而不是變量,然而你依然可以更改里面的frameRate,因為這兩個常量本身不會改變,它們并不存儲這個nextMode實例,在后臺僅僅是對nextMode的引用,所以,改變的是被引用的基礎nextModeframeRate參數,而不改變常量的值。

1. 恒等運算符

??因為類是引用類型,有可能有多個常量和變量在后臺同時引用某一個類實例,如果能夠判斷兩個常量或者變量是否引用同一個類實例將會很有幫助,為了這個目的,swift內建了兩個恒等運算。

  • 等價于(===)
  • 不等價于(!==)

看下面這個例子。

class JJSwiftVC: UIViewController
{
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.lightGray
        
        let resolution = Resolution()
        let mode = VideoMode()
        mode.resolution = resolution
        mode.interlaced = false
        mode.name = "10086"
        mode.frameRate = 25.0
        
        let nextMode = mode
        nextMode.frameRate = 30.0
        print(mode.frameRate)
        print(nextMode.frameRate)
        
        if mode === nextMode {
            print("They are the same instance !")
        }
        else {
            print("They are not the same instance !")
        }
    }
}

下面看輸出結果

30.0
30.0
They are the same instance !

這里還要注意=====的不同:

  • ===表示兩個類類型的常量或者變量是否引用同一個類實例。
  • ==表示兩個實例的值相等或者相同。

2. 指針

??對于COC,你知道使用指針來引用內存中的地址,一個swift常量或者變量引用一個引用類型的實例與C語言中的指針類似,不同的是并不直接指向內存中的某個地址,而且也不要求你使用星號*來表明你在創見意一個引用,swift中這些引用于其他的常量或者變量的定義方式相同。


類和結構體的選擇

??在選擇之前要記住,結構體是值類型,類是引用類型,按照通用標準,當符合下面的條件時,請考慮結構體。

  • 結構體的主要目的是用來封裝少量相關簡單數據值。
  • 有理由預計一個結構體實例在賦值或傳遞時,封裝的數據將會被拷貝而不是被引用。
  • 任何在結構體中存儲的值類型屬性,也將會被拷貝,而不是被引用。
  • 結構體不需要去繼承另一個已存在類型的屬性或者行為。

簡單舉幾個適合結構體的例子。

  • 幾何形狀的大小
  • 一定范圍內的路徑
  • 三維坐標系內一點

在所有其他案例匯中,基本都是定義一個類,生成一個它的實例。


集合類型的賦值和拷貝行為

??swift中的字符串String、數組Array和字典Dictionary類型均以結構體的形式實現,這意味著,StringArrayDictionary類型的數據被賦值給新的變量或者常量,或者被傳入函數方法中,它們的值會發生拷貝行為(值傳遞方式)。

??而在OC中字符串NSString、數組NSArray和字典NSDictionary類型均以類的形式出現,這與swift中以值傳遞的方式是不同的,字符串NSString、數組NSArray和字典NSDictionary在發生賦值或者傳入函數方法中時,不會發生值拷貝,而是傳遞已存在實例的引用。

注意:實際上,在你的代碼中,數組字典字符串的拷貝好像確實是在有拷貝行為的地方產生過,然而,在swift后臺中,只有確有必要,actural實際拷貝才會被執行,swift管理拷貝以確保最優化的性能,所以你也沒有必要去避免賦值以保證最優性能,實際賦值由系統管理優化。

后記

未完,待續~~~

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

推薦閱讀更多精彩內容