協(xié)議定義了一個藍(lán)圖汇歹,規(guī)定了用來實現(xiàn)某一特定任務(wù)或者功能的方法椅棺、屬性犁罩,以及其他需要的東西。類两疚、結(jié)構(gòu)體或枚舉都可以采納協(xié)議床估,并為協(xié)議定義的這些要求提供具體實現(xiàn)。某個類型能夠滿足某個協(xié)議的要求诱渤,就可以說該類型“符合”這個協(xié)議丐巫。
除了采納協(xié)議的類型必須實現(xiàn)的要求外,還可以對協(xié)議進行擴展勺美,通過擴展來實現(xiàn)一部分要求或者實現(xiàn)一些附加功能递胧,這樣采納協(xié)議的類型就能夠使用這些功能。
屬性要求
1赡茸、協(xié)議總是用var關(guān)鍵字來聲明變量屬性缎脾,在類型聲明后加上{ set get }來表示屬性是可讀可寫的,可讀屬性則用{ get }來表示
2占卧、在協(xié)議中定義類型屬性時遗菠,總是使用static關(guān)鍵字作為前綴联喘。當(dāng)類類型采納協(xié)議時,除了static關(guān)鍵字辙纬,還可以使用class關(guān)鍵字來聲明類型屬性
??類型屬性 ?可以為類型本身定義屬性耸袜,無論創(chuàng)建了多少個該類型的實例,這些屬性都只有唯一一份牲平。這種屬性就是類型屬性
類型屬性用于定義某個類型所有實例共享的數(shù)據(jù),比如所有實例都能用的一個常量(就像 C 語言中的靜態(tài)常量)域滥,或者所有實例都能訪問的一個變量(就像 C 語言中的靜態(tài)變量)纵柿。
protocol AnotherProtocol?{ staticvarsomeTypeProperty: Int {get set}}
??如果協(xié)議要求未被完全滿足,在編譯時會報錯
方法要求
1启绰、協(xié)議可以要求采納協(xié)議的類型實現(xiàn)某些指定的實例方法或類方法昂儒。這些方法作為協(xié)議的一部分,像普通方法一樣放在協(xié)議的定義中委可,但是不需要大括號和方法體渊跋。可以在協(xié)議中定義具有可變參數(shù)的方法着倾,和普通方法的定義方式相同拾酝。但是,不支持為協(xié)議中的方法的參數(shù)提供默認(rèn)值卡者。
正如屬性要求中所述蒿囤,在協(xié)議中定義類方法的時候,總是使用static關(guān)鍵字作為前綴崇决。當(dāng)類類型采納協(xié)議時材诽,除了static關(guān)鍵字,還可以使用class關(guān)鍵字作為前綴
2恒傻、有時需要在方法中改變方法所屬的實例脸侥。例如,在值類型(即結(jié)構(gòu)體和枚舉)的實例方法中盈厘,將mutating關(guān)鍵字作為方法的前綴睁枕,寫在func關(guān)鍵字之前,表示可以在該方法中修改它所屬的實例以及實例的任意屬性的值扑庞。
3譬重、協(xié)議可以要求采納協(xié)議的類型實現(xiàn)指定的構(gòu)造器。你可以在采納協(xié)議的類中實現(xiàn)構(gòu)造器罐氨,無論是作為指定構(gòu)造器臀规,還是作為便利構(gòu)造器。無論哪種情況栅隐,你都必須為構(gòu)造器實現(xiàn)標(biāo)上required修飾符
??如果一個子類重寫了父類的指定構(gòu)造器塔嬉,并且該構(gòu)造器滿足了某個協(xié)議的要求玩徊,那么該構(gòu)造器的實現(xiàn)需要同時標(biāo)注required和override修飾符
協(xié)議作為類型
盡管協(xié)議本身并未實現(xiàn)任何功能,但是協(xié)議可以被當(dāng)做一個成熟的類型來使用谨究。
協(xié)議的類型的實例都可以賦值
委托(代理)模式
委托是一種設(shè)計模式恩袱,它允許類或結(jié)構(gòu)體將一些需要它們負(fù)責(zé)的功能委托給其他類型的實例。委托模式的實現(xiàn)很簡單:定義協(xié)議來封裝那些需要被委托的功能胶哲,這樣就能確保采納協(xié)議的類型能提供這些功能畔塔。委托模式可以用來響應(yīng)特定的動作,或者接收外部數(shù)據(jù)源提供的數(shù)據(jù)鸯屿,而無需關(guān)心外部數(shù)據(jù)源的類型澈吨。
通過擴展添加協(xié)議一致性
即便無法修改源代碼,依然可以通過擴展令已有類型采納并符合協(xié)議寄摆。擴展可以為已有類型添加屬性谅辣、方法、下標(biāo)以及構(gòu)造器婶恼,因此可以符合協(xié)議中的相應(yīng)要求桑阶。
通過擴展采納協(xié)議
當(dāng)一個類型已經(jīng)符合了某個協(xié)議中的所有要求,卻還沒有聲明采納該協(xié)議時勾邦,可以通過空擴展體的擴展來采納該協(xié)議
協(xié)議的繼承
協(xié)議能夠繼承一個或多個其他協(xié)議蚣录,可以在繼承的協(xié)議的基礎(chǔ)上增加新的要求。協(xié)議的繼承語法與類的繼承相似眷篇,多個被繼承的協(xié)議間用逗號分隔
類類型專屬協(xié)議
你可以在協(xié)議的繼承列表中包归,通過添加class關(guān)鍵字來限制協(xié)議只能被類類型采納,而結(jié)構(gòu)體或枚舉不能采納該協(xié)議铅歼。class關(guān)鍵字必須第一個出現(xiàn)在協(xié)議的繼承列表中公壤,在其他繼承的協(xié)議之前:
protocol ? SomeClassOnlyProtocol: class, SomeInheritedProtocol{ ? // 這里是類類型專屬協(xié)議的定義部分 ?}
協(xié)議合成
有時候需要同時采納多個協(xié)議,你可以將多個協(xié)議采用SomeProtocol & AnotherProtocol這樣的格式進行組合椎椰,稱為協(xié)議合成
檢查協(xié)議一致性
你可以使用類型轉(zhuǎn)換中描述的is和as操作符來檢查協(xié)議一致性厦幅,即是否符合某協(xié)議,并且可以轉(zhuǎn)換到指定的協(xié)議類型慨飘。檢查和轉(zhuǎn)換到某個協(xié)議類型在語法上和類型的檢查和轉(zhuǎn)換完全相同:
is用來檢查實例是否符合某個協(xié)議确憨,若符合則返回true,否則返回false瓤的。
as?返回一個可選值休弃,當(dāng)實例符合某個協(xié)議時,返回類型為協(xié)議類型的可選值圈膏,否則返回nil塔猾。
as!將實例強制向下轉(zhuǎn)換到某個協(xié)議類型,如果強轉(zhuǎn)失敗稽坤,會引發(fā)運行時錯誤丈甸。
可選的協(xié)議要求
協(xié)議可以定義可選要求糯俗,采納協(xié)議的類型可以選擇是否實現(xiàn)這些要求。在協(xié)議中使用optional關(guān)鍵字作為前綴來定義可選要求睦擂。
協(xié)議擴展
協(xié)議可以通過擴展來為采納協(xié)議的類型提供屬性得湘、方法以及下標(biāo)的實現(xiàn)。通過這種方式顿仇,你可以基于協(xié)議本身來實現(xiàn)這些功能淘正,而無需在每個采納協(xié)議的類型中都重復(fù)同樣的實現(xiàn),也無需使用全局函數(shù)臼闻。
通過協(xié)議擴展跪帝,所有采納協(xié)議的類型,都能自動獲得這個擴展所增加的方法實現(xiàn)些阅,無需任何額外修改,如果采納協(xié)議的類型為這些要求提供了自己的實現(xiàn)斑唬,那么這些自定義實現(xiàn)將會替代擴展中的默認(rèn)實現(xiàn)被使用市埋。
為協(xié)議擴展添加限制條件
在擴展協(xié)議的時候,可以指定一些限制條件恕刘,只有采納協(xié)議的類型滿足這些限制條件時缤谎,才能獲得協(xié)議擴展提供的默認(rèn)實現(xiàn)。這些限制條件寫在協(xié)議名之后褐着,使用where子句來描述