swift學(xué)習(xí)筆記4——擴(kuò)展赴蝇、協(xié)議

之前學(xué)習(xí)swift時(shí)的個(gè)人筆記恢总,根據(jù)github:the-swift-programming-language-in-chinese學(xué)習(xí)迎罗、總結(jié),將重要的內(nèi)容提取片仿,加以理解后整理為學(xué)習(xí)筆記纹安,方便以后查詢用。詳細(xì)可以參考the-swift-programming-language-in-chinese砂豌,或者蘋果官方英文版文檔

當(dāng)前版本是swift2.2

擴(kuò)展(Extensions)

擴(kuò)展 就是為一個(gè)已有的類厢岂、結(jié)構(gòu)體、枚舉類型或者協(xié)議類型添加新功能阳距。這包括在沒(méi)有權(quán)限獲取原始源代碼的情況下擴(kuò)展類型的能力(即 逆向建模 )塔粒。擴(kuò)展和 Objective-C 中的分類類似。(與 Objective-C 不同的是筐摘,Swift 的擴(kuò)展沒(méi)有名字卒茬。)

如果你通過(guò)擴(kuò)展為一個(gè)已有類型添加新功能,那么新功能對(duì)該類型的所有已有實(shí)例都是可用的咖熟,即使它們是在這個(gè)擴(kuò)展定義之前創(chuàng)建的圃酵。

計(jì)算型屬性(Computed Properties)

擴(kuò)展可以為已有類型添加計(jì)算型實(shí)例屬性和計(jì)算型類型屬性。不可以添加存儲(chǔ)性屬性

構(gòu)造器(Initializers)

擴(kuò)展可以為已有類型添加新的構(gòu)造器馍管。這可以讓你擴(kuò)展其它類型郭赐,將你自己的定制類型作為其構(gòu)造器參數(shù),或者提供該類型的原始實(shí)現(xiàn)中未提供的額外初始化選項(xiàng)确沸。

擴(kuò)展能為類添加新的便利構(gòu)造器捌锭,但是它們不能為類添加新的指定構(gòu)造器或析構(gòu)器躬存。指定構(gòu)造器和析構(gòu)器必須總是由原始的類實(shí)現(xiàn)來(lái)提供。

方法(Methods)

擴(kuò)展可以為已有類型添加新的實(shí)例方法和類型方法舀锨。

可變實(shí)例方法(Mutating Instance Methods)

通過(guò)擴(kuò)展添加的實(shí)例方法也可以修改該實(shí)例本身岭洲。結(jié)構(gòu)體和枚舉類型中修改 self 或其屬性的方法必須將該實(shí)例方法標(biāo)注為 mutating,正如來(lái)自原始實(shí)現(xiàn)的可變方法一樣坎匿。

下面的例子為 Swift 的 Int 類型添加了一個(gè)名為 square 的可變方法盾剩,用于計(jì)算原始值的平方值:

extension Int {
    mutating func square() {
        self = self * self
    }
}

下標(biāo)(Subscripts)

擴(kuò)展可以為已有類型添加新下標(biāo)。這個(gè)例子為 Swift 內(nèi)建類型 Int 添加了一個(gè)整型下標(biāo)替蔬。該下標(biāo) [n] 返回十進(jìn)制數(shù)字從右向左數(shù)的第 n 個(gè)數(shù)字:

123456789[0] 返回 9
123456789[1] 返回 8

嵌套類型(Nested Types)

擴(kuò)展可以為已有的類告私、結(jié)構(gòu)體和枚舉添加新的嵌套類型:

協(xié)議

Mutating 方法要求

如果你在協(xié)議中定義了一個(gè)實(shí)例方法,該方法會(huì)改變采納該協(xié)議的類型的實(shí)例承桥,那么在定義協(xié)議時(shí)需要在方法前加 mutating 關(guān)鍵字驻粟。這使得結(jié)構(gòu)體和枚舉能夠采納此協(xié)議并滿足此方法要求。

將 mutating 關(guān)鍵字作為方法的前綴凶异,寫在 func 關(guān)鍵字之前蜀撑,表示可以在該方法中修改它所屬的實(shí)例以及實(shí)例的任意屬性的值

實(shí)現(xiàn)協(xié)議中的 mutating 方法時(shí),若是類類型剩彬,則不用寫 mutating 關(guān)鍵字酷麦。而對(duì)于結(jié)構(gòu)體和枚舉,則必須寫 mutating 關(guān)鍵字喉恋。

協(xié)議構(gòu)造器要求

協(xié)議可以要求采納協(xié)議的類型實(shí)現(xiàn)指定的構(gòu)造器沃饶。你可以像編寫普通構(gòu)造器那樣,在協(xié)議的定義里寫下構(gòu)造器的聲明轻黑,但不需要寫花括號(hào)和構(gòu)造器的實(shí)體:

protocol SomeProtocol {
    init(someParameter: Int)
}

構(gòu)造器要求在類中的實(shí)現(xiàn)

你可以在采納協(xié)議的類中實(shí)現(xiàn)構(gòu)造器糊肤,無(wú)論是作為指定構(gòu)造器,還是作為便利構(gòu)造器氓鄙。無(wú)論哪種情況馆揉,你都必須為構(gòu)造器實(shí)現(xiàn)標(biāo)上 required 修飾符:

class SomeClass: SomeProtocol {
    required init(someParameter: Int) {
        // 這里是構(gòu)造器的實(shí)現(xiàn)部分
    }
}

使用 required 修飾符可以確保所有子類也必須提供此構(gòu)造器實(shí)現(xiàn),從而也能符合協(xié)議玖详。

構(gòu)造器要求
協(xié)議可以要求采納協(xié)議的類型實(shí)現(xiàn)指定的構(gòu)造器把介。你可以像編寫普通構(gòu)造器那樣勤讽,在協(xié)議的定義里寫下構(gòu)造器的聲明蟋座,但不需要寫花括號(hào)和構(gòu)造器的實(shí)體:

protocol SomeProtocol {
init(someParameter: Int)
}
構(gòu)造器要求在類中的實(shí)現(xiàn)

你可以在采納協(xié)議的類中實(shí)現(xiàn)構(gòu)造器,無(wú)論是作為指定構(gòu)造器脚牍,還是作為便利構(gòu)造器向臀。無(wú)論哪種情況,你都必須為構(gòu)造器實(shí)現(xiàn)標(biāo)上 required 修飾符:

class SomeClass: SomeProtocol {
    required init(someParameter: Int) {
        // 這里是構(gòu)造器的實(shí)現(xiàn)部分
    }
}

使用 required 修飾符可以確保所有子類也必須提供此構(gòu)造器實(shí)現(xiàn)诸狭,從而也能符合協(xié)議券膀。

如果一個(gè)子類重寫了父類的指定構(gòu)造器君纫,并且該構(gòu)造器滿足了某個(gè)協(xié)議的要求,那么該構(gòu)造器的實(shí)現(xiàn)需要同時(shí)標(biāo)注 required 和 override 修飾符:

protocol SomeProtocol {
    init()
}

class SomeSuperClass {
    init() {
        // 這里是構(gòu)造器的實(shí)現(xiàn)部分
    }
}

class SomeSubClass: SomeSuperClass, SomeProtocol {
    // 因?yàn)椴杉{協(xié)議芹彬,需要加上 required
    // 因?yàn)槔^承自父類蓄髓,需要加上 override
    required override init() {
        // 這里是構(gòu)造器的實(shí)現(xiàn)部分
    }
}

如果類已經(jīng)被標(biāo)記為 final,那么不需要在協(xié)議構(gòu)造器的實(shí)現(xiàn)中使用 required 修飾符舒帮,因?yàn)?final 類不能有子類

協(xié)議作為類型

盡管協(xié)議本身并未實(shí)現(xiàn)任何功能会喝,但是協(xié)議可以被當(dāng)做一個(gè)成熟的類型來(lái)使用。

  • 作為函數(shù)玩郊、方法或構(gòu)造器中的參數(shù)類型或返回值類型
  • 作為常量肢执、變量或?qū)傩缘念愋?/li>
  • 作為數(shù)組、字典或其他容器中的元素類型

通過(guò)擴(kuò)展采納協(xié)議

當(dāng)一個(gè)類型已經(jīng)符合了某個(gè)協(xié)議中的所有要求译红,卻還沒(méi)有聲明采納該協(xié)議時(shí)预茄,可以通過(guò)空擴(kuò)展體的擴(kuò)展來(lái)采納該協(xié)議:

struct Hamster {
    var name: String
    var textualDescription: String {
        return "A hamster named \(name)"
    }
}
extension Hamster: TextRepresentable {}

從現(xiàn)在起,Hamster 的實(shí)例可以作為 TextRepresentable 類型使用:

let simonTheHamster = Hamster(name: "Simon")
let v1: TextRepresentable = simonTheHamster // 可以賦值
print(v1.textualDescription)

即使?jié)M足了協(xié)議的所有要求侦厚,類型也不會(huì)自動(dòng)采納協(xié)議耻陕,必須顯式地采納協(xié)議。

協(xié)議類型的集合

協(xié)議類型可以在數(shù)組或者字典這樣的集合中使用刨沦,在協(xié)議類型提到了這樣的用法淮蜈。下面的例子創(chuàng)建了一個(gè)元素類型為 TextRepresentable 的數(shù)組:

let things: [TextRepresentable] = [game, d12, simonTheHamster]
如下所示,可以遍歷 things 數(shù)組已卷,并打印每個(gè)元素的文本表示:

for thing in things {
    print(thing.textualDescription)
}
// A game of Snakes and Ladders with 25 squares
// A 12-sided dice
// A hamster named Simon

thing 是 TextRepresentable 類型而不是 Dice梧田,DiceGame,Hamster 等類型侧蘸,即使實(shí)例在幕后確實(shí)是這些類型中的一種裁眯。由于 thing 是 TextRepresentable 類型,任何 TextRepresentable 的實(shí)例都有一個(gè) textualDescription 屬性讳癌,所以在每次循環(huán)中可以安全地訪問(wèn) thing.textualDescription穿稳。

協(xié)議的繼承

協(xié)議能夠繼承一個(gè)或多個(gè)其他協(xié)議,可以在繼承的協(xié)議的基礎(chǔ)上增加新的要求晌坤。協(xié)議的繼承語(yǔ)法與類的繼承相似逢艘,多個(gè)被繼承的協(xié)議間用逗號(hào)分隔:

protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
    // 這里是協(xié)議的定義部分
}

類類型專屬協(xié)議

你可以在協(xié)議的繼承列表中,通過(guò)添加 class 關(guān)鍵字來(lái)限制協(xié)議只能被類類型采納骤菠,而結(jié)構(gòu)體或枚舉不能采納該協(xié)議它改。class 關(guān)鍵字必須第一個(gè)出現(xiàn)在協(xié)議的繼承列表中,在其他繼承的協(xié)議之前:

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
    // 這里是類類型專屬協(xié)議的定義部分
}

在以上例子中商乎,協(xié)議 SomeClassOnlyProtocol 只能被類類型采納央拖。如果嘗試讓結(jié)構(gòu)體或枚舉類型采納該協(xié)議,則會(huì)導(dǎo)致編譯錯(cuò)誤。

協(xié)議合成

有時(shí)候需要同時(shí)采納多個(gè)協(xié)議鲜戒,你可以將多個(gè)協(xié)議采用 protocol<SomeProtocol, AnotherProtocol> 這樣的格式進(jìn)行組合专控,稱為 協(xié)議合成(protocol composition)。你可以在 <> 中羅列任意多個(gè)你想要采納的協(xié)議遏餐,以逗號(hào)分隔伦腐。

下面的例子中,將 Named 和 Aged 兩個(gè)協(xié)議按照上述語(yǔ)法組合成一個(gè)協(xié)議失都,作為函數(shù)參數(shù)的類型:

protocol Named {
    var name: String { get }
}
protocol Aged {
    var age: Int { get }
}
struct Person: Named, Aged {
    var name: String
    var age: Int
}
func wishHappyBirthday(celebrator: protocol<Named, Aged>) {
    print("Happy birthday \(celebrator.name) - you're \(celebrator.age)!")
}

協(xié)議合成并不會(huì)生成新的蔗牡、永久的協(xié)議類型,而是將多個(gè)協(xié)議中的要求合成到一個(gè)只在局部作用域有效的臨時(shí)協(xié)議中嗅剖。

可選的協(xié)議要求

協(xié)議可以定義可選要求辩越,采納協(xié)議的類型可以選擇是否實(shí)現(xiàn)這些要求。在協(xié)議中使用 optional 關(guān)鍵字作為前綴來(lái)定義可選要求信粮。使用可選要求時(shí)(例如黔攒,可選的方法或者屬性),它們的類型會(huì)自動(dòng)變成可選的强缘。比如督惰,一個(gè)類型為 (Int) -> String 的方法會(huì)變成 ((Int) -> String)?。需要注意的是整個(gè)函數(shù)類型是可選的旅掂,而不是函數(shù)的返回值赏胚。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市商虐,隨后出現(xiàn)的幾起案子觉阅,更是在濱河造成了極大的恐慌,老刑警劉巖秘车,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件典勇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡叮趴,警方通過(guò)查閱死者的電腦和手機(jī)割笙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)眯亦,“玉大人伤溉,你說(shuō)我怎么就攤上這事∑蘼剩” “怎么了乱顾?”我有些...
    開(kāi)封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)舌涨。 經(jīng)常有香客問(wèn)我糯耍,道長(zhǎng)扔字,這世上最難降的妖魔是什么囊嘉? 我笑而不...
    開(kāi)封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任温技,我火速辦了婚禮,結(jié)果婚禮上扭粱,老公的妹妹穿的比我還像新娘舵鳞。我一直安慰自己,他們只是感情好琢蛤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布蜓堕。 她就那樣靜靜地躺著,像睡著了一般博其。 火紅的嫁衣襯著肌膚如雪套才。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天慕淡,我揣著相機(jī)與錄音背伴,去河邊找鬼。 笑死峰髓,一個(gè)胖子當(dāng)著我的面吹牛傻寂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播携兵,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼疾掰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了徐紧?” 一聲冷哼從身側(cè)響起静檬,我...
    開(kāi)封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎并级,沒(méi)想到半個(gè)月后巴柿,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡死遭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年广恢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呀潭。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡钉迷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出钠署,到底是詐尸還是另有隱情糠聪,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布谐鼎,位于F島的核電站舰蟆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜身害,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一味悄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧塌鸯,春花似錦侍瑟、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至茧球,卻和暖如春庭瑰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抢埋。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工弹灭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人羹令。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓鲤屡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親福侈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子酒来,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1、范型范型所解決的問(wèn)題 函數(shù)肪凛、方法堰汉、類型:類,結(jié)構(gòu)體伟墙,枚舉翘鸭,元組類型,協(xié)議參數(shù)戳葵,返回值就乓,成員函數(shù)參數(shù),成員屬性類...
    我是小胡胡分胡閱讀 816評(píng)論 0 1
  • 132.轉(zhuǎn)換錯(cuò)誤成可選值 通過(guò)轉(zhuǎn)換錯(cuò)誤成一個(gè)可選值,你可以使用 try? 來(lái)處理錯(cuò)誤拱烁。當(dāng)執(zhí)行try?表達(dá)式時(shí),如果...
    無(wú)灃閱讀 1,237評(píng)論 0 3
  • 本章將會(huì)介紹 協(xié)議語(yǔ)法屬性要求方法要求(Method Requirements)Mutating 方法要求構(gòu)造器要...
    寒橋閱讀 413評(píng)論 0 3
  • Swift屬性 Swift屬性將值跟特定的類生蚁,結(jié)構(gòu)體,枚舉關(guān)聯(lián)戏自。分為存儲(chǔ)屬性和計(jì)算屬性邦投,通常用于特定類型的實(shí)例。屬...
    小小廚師閱讀 837評(píng)論 0 0
  • 協(xié)議語(yǔ)法 實(shí)現(xiàn)協(xié)議 擁有父類的類在采納協(xié)議時(shí)擅笔,應(yīng)該將父類名放在協(xié)議名之前志衣,以逗號(hào)分隔: 協(xié)議的屬性要求 協(xié)議不指定...
    666真666閱讀 1,690評(píng)論 0 2