Swift 結(jié)構(gòu)體

對(duì) Swift 學(xué)習(xí) 的一些總結(jié)
學(xué)習(xí)文獻(xiàn):
Chris Eidhof. “Swift 進(jìn)階”

類與結(jié)構(gòu)體的主要不同點(diǎn)

  • 語(yǔ)義:

類:引用類型(引用語(yǔ)義)弄匕,需要自己管理其引用計(jì)數(shù)、引用值得變化
結(jié)構(gòu)體: 值類型(值語(yǔ)義)嘀粱,在設(shè)計(jì)結(jié)構(gòu)體時(shí),我們可以要求編譯器保證不可變性侨核。

  • 內(nèi)存管理方式:

類:類的實(shí)例只能通過(guò)引用來(lái)間接地訪問(wèn)草穆。類能有很多個(gè)持有者。
結(jié)構(gòu)體:可以被直接持有及訪問(wèn)搓译,不會(huì)被引用悲柱,但是會(huì)被復(fù)制。也就是說(shuō)些己,結(jié)構(gòu)體的持有者是唯一的豌鸡。

  • 共享代碼:

類: 通過(guò)繼承來(lái)共享代碼
結(jié)構(gòu)體 (以及枚舉):不能被繼承嘿般。想要在不同的結(jié)構(gòu)體或者枚舉之間共享代碼,我們需要使用不同的技術(shù)涯冠,比如像是組合炉奴、泛型以及協(xié)議擴(kuò)展等。

值類型

值永遠(yuǎn)不會(huì)改變蛇更,它們具有不可變的特性瞻赶。這 (在絕大多數(shù)情況下) 是一件好事,因?yàn)槭褂貌蛔兊臄?shù)據(jù)可以讓代碼更容易被理解派任。不可變性也讓代碼天然地具有線程安全的特性砸逊,因?yàn)椴荒芨淖兊臇|西是可以在線程之間安全地共享的。

值語(yǔ)義

  1. 結(jié)構(gòu)體不能通過(guò)引用來(lái)進(jìn)行比較掌逛,只能通過(guò)它們的屬性來(lái)比較兩個(gè)結(jié)構(gòu)體师逸。雖然可以用 var 來(lái)在結(jié)構(gòu)體中聲明可變的變量屬性,但是這個(gè)可變性只體現(xiàn)在變量本身上豆混,而不是指里面的值篓像。改變一個(gè)結(jié)構(gòu)體變量的屬性,在概念上來(lái)說(shuō)皿伺,和為整個(gè)變量賦值一個(gè)全新的結(jié)構(gòu)體是等價(jià)的员辩。我們總是使用一個(gè)新的結(jié)構(gòu)體,并設(shè)置被改變的屬性值心傀,然后用它替代原來(lái)的結(jié)構(gòu)體屈暗。
  2. 結(jié)構(gòu)體只有一個(gè)持有者。比如脂男,當(dāng)我們將結(jié)構(gòu)體變量傳遞給一個(gè)函數(shù)時(shí)养叛,函數(shù)將接收到結(jié)構(gòu)體的復(fù)制,它也只能改變它自己的這份復(fù)制宰翅。這叫做值語(yǔ)義 (value semantics) (又作復(fù)制語(yǔ)義)

引用語(yǔ)義

類對(duì)象會(huì)擁有很多持有者弃甥,這被叫做引用語(yǔ)義 (reference semantics)。

結(jié)構(gòu)體

結(jié)構(gòu)體為值類型

值類型意味著一個(gè)值變量被復(fù)制時(shí)汁讼,這個(gè)值本身也會(huì)被復(fù)制淆攻,而不只限于對(duì)這個(gè)值的引用的復(fù)制。在幾乎所有的編程語(yǔ)言中嘿架,標(biāo)量類型都是值類型瓶珊。這意味著當(dāng)一個(gè)值被賦給新的變量時(shí),并不是傳遞引用耸彪,而是進(jìn)行值的復(fù)制伞芹。

let a = 12
let b = a 
a += 1 
print (a) // 13
print (b) // 12
b的值沒(méi)有根據(jù)a的值進(jìn)行改變

結(jié)構(gòu)體的賦值 特點(diǎn)

  1. 定義結(jié)構(gòu)體 PY_Point 它里面有一個(gè) let x = 12, 以及var y, 可以比較 y是否大于x
   struct PY_Point {
        let x = 12
        var y = 0
        func isReaterThanX() -> Bool {
            return y > x
        }
    }
  1. 賦值: 下面打印結(jié)果表示 兩個(gè)結(jié)構(gòu)體已經(jīng)不是同一個(gè)結(jié)構(gòu)體了。發(fā)生了復(fù)制現(xiàn)象唱较。
       var point = PY_Point(y: 13)
        var pointTemp = point
    
        withUnsafePointer(to: &point) { pointAddress in
            print("point 地址: \(pointAddress)")
        }
        withUnsafePointer(to: &pointTemp) {pointTempAddress in
            print("pointTemp 地址: \(pointTempAddress)")
        }
        /**
         point 地址: 0x00007ffeec4d7a00
         pointTemp 地址: 0x00007ffeec4d7a10
         */
  1. 結(jié)構(gòu)體(值類型)內(nèi)部賦值:

可以看到扎唾,多次調(diào)用了didSet 方法,但是pointTemp的地址沒(méi)有改變
“理解值類型的關(guān)鍵就是理解為什么這里會(huì)被調(diào)用南缓。對(duì)結(jié)構(gòu)體進(jìn)行改變胸遇,在語(yǔ)義上來(lái)說(shuō),與重新為它進(jìn)行賦值是相同的汉形。當(dāng)我們改變了結(jié)構(gòu)體中某個(gè)深層次的屬性時(shí)纸镊,其實(shí)還是意味著我們改變了結(jié)構(gòu)體,所以 didSet 依然會(huì)被觸發(fā)获雕。
雖然語(yǔ)義上來(lái)說(shuō)薄腻,我們將整個(gè)結(jié)構(gòu)體替換為了新的結(jié)構(gòu)體,但是編譯器依然會(huì)原地進(jìn)行變更届案。由于這個(gè)結(jié)構(gòu)體沒(méi)有其他所有者,實(shí)際上我們沒(méi)有必要進(jìn)行復(fù)制罢艾。不過(guò)如果有多個(gè)持有者的話楣颠,重新賦值意味著發(fā)生復(fù)制。對(duì)于寫時(shí)復(fù)制的結(jié)構(gòu)體咐蚯,工作方式會(huì)略有不同

   var pointTemp: PY_Point? = PY_Point(y: 13) {
        didSet {
            print("pointTemp didSet 調(diào)用了")
        }
    }
 func valuation() {
    withUnsafePointer(to: &pointTemp) {pointTempAddress in
            print("pointTemp 地址: \(pointTempAddress)")
        }
        pointTemp?.y = -1
        withUnsafePointer(to: &pointTemp) {pointTempAddress in
            print("pointTemp 地址: \(pointTempAddress)")
        }
    }
//調(diào)用valuation()打印結(jié)果為 
/**
pointTemp 地址: 0x00007ffee9379a00
pointTemp didSet 調(diào)用了
pointTemp didSet 調(diào)用了
pointTemp 地址: 0x00007ffee9379a00
pointTemp didSet 調(diào)用了
*/

結(jié)構(gòu)體內(nèi)建方法

  1. 結(jié)構(gòu)體可以添加方法 ,比如比較x童漩,y大小的方法
struct PY_Point {
        let x = 12
        var y = 0
        func isReaterThanX() -> Bool {
            return y > x
        }
    }
  1. 結(jié)構(gòu)體方法中修改自身的屬性值

編譯器自動(dòng)補(bǔ)充了關(guān)鍵詞 mutating
對(duì)不可變x屬性,提示了Left side of mutating operator isn't mutable: 'x' is a 'let' constant (x為let 修飾春锋,值不能被修改)

extension PY_Point {
    mutating func y_offset1() {
        y += 1
    }

    mutating func x_offset1() {
///報(bào)錯(cuò) Left side of mutating operator isn't mutable: 'x' is a 'let' constant
        x += 1
    }
}

mutating / inout關(guān)鍵詞

  • inout: 函數(shù)中矫膨,我們可以將參數(shù)標(biāo)記為 inout 來(lái)使其可變。就和一個(gè)普通的參數(shù)一樣期奔,值被復(fù)制并作為參數(shù)被傳到函數(shù)內(nèi)侧馅。不過(guò),我們可以改變這個(gè)復(fù)制 (就好像它是被 var 定義的一樣)呐萌。然后當(dāng)函數(shù)返回時(shí)馁痴,原來(lái)的值將被覆蓋掉。
postfix func ++ (left: inout CGFloat) {
    left += 1
}
 var a:CGFloat = 1
        a++ 
        print(a)
// 打印結(jié)果為 2.0
  • mutating: 函數(shù)體內(nèi)部你可以隨時(shí)使用 self肺孤。如果我們想要改變 self罗晕,或是改變 self 自身或者嵌套的 (比如 self.y) 任何屬性,我們就需要將方法標(biāo)記為 mutating.mutating 將隱式的 self 參數(shù)變?yōu)榭勺兊脑拢⑶腋淖兞诉@個(gè)變量的值小渊。
  • mutating 其實(shí)和inout做了同樣的事情,它將隱式的 self 參數(shù)變?yōu)榭勺兊拿0龋⑶腋淖兞诉@個(gè)變量的值

寫時(shí)復(fù)制

在 Swift 標(biāo)準(zhǔn)庫(kù)中酬屉, Array、Dictionary杂靶、 Set 這樣的集合類型是通過(guò)一種叫做寫時(shí)復(fù)制 (copy-on-write) 的技術(shù)實(shí)現(xiàn)的梆惯。
請(qǐng)參考 Swift 寫時(shí)復(fù)制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末酱鸭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子垛吗,更是在濱河造成了極大的恐慌凹髓,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怯屉,死亡現(xiàn)場(chǎng)離奇詭異蔚舀,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)锨络,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門赌躺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人羡儿,你說(shuō)我怎么就攤上這事礼患。” “怎么了掠归?”我有些...
    開(kāi)封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵缅叠,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我虏冻,道長(zhǎng)肤粱,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任厨相,我火速辦了婚禮领曼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蛮穿。我一直安慰自己庶骄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布绪撵。 她就那樣靜靜地躺著瓢姻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪音诈。 梳的紋絲不亂的頭發(fā)上幻碱,一...
    開(kāi)封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音细溅,去河邊找鬼褥傍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛喇聊,可吹牛的內(nèi)容都是我干的恍风。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼朋贬!你這毒婦竟也來(lái)了凯楔?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤锦募,失蹤者是張志新(化名)和其女友劉穎摆屯,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體糠亩,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡虐骑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赎线。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廷没。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖垂寥,靈堂內(nèi)的尸體忽然破棺而出颠黎,到底是詐尸還是另有隱情,我是刑警寧澤滞项,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布盏缤,位于F島的核電站,受9級(jí)特大地震影響蓖扑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜台舱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一律杠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竞惋,春花似錦柜去、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至浑厚,卻和暖如春股耽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背钳幅。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工物蝙, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人敢艰。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓诬乞,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子震嫉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354