Objective-C中的協(xié)議和非正式協(xié)議

協(xié)議(Protocol)

協(xié)議就是聲明方法的集合,它表示對象的行為。協(xié)議與具體實(shí)現(xiàn)無關(guān),它是根據(jù)消息來獲取對象的一套系統(tǒng)化的方法。如果能夠熟練掌握協(xié)議的使用,就能夠定義出高靈活性、低耦合性的類。

看起來很難懂的樣子,那我們就從一個(gè)最常見的、具體的例子開始。

UITableViewDelegate && UITableViewDataSource

UITableView是iOS中最常用的組件,對UITableViewDelegate和UITableViewDataSource我們肯定不會感到陌生,他們就是兩個(gè)協(xié)議。

在我們的view controller中實(shí)現(xiàn)了UITableViewDelegate和UITableViewDataSource聲明的方法,UITableView調(diào)用這些方法,這就是一個(gè)協(xié)議的工作流程

聲明協(xié)議

協(xié)議采用如下方式聲明:

@protocol 協(xié)議名
@required
聲明方法1
聲明方法2
...

@optional
聲明方法3
聲明方法4
...

@end

required代表采用協(xié)議的類必須實(shí)現(xiàn)的方法,optional代表采用協(xié)議的類可選的實(shí)現(xiàn)方法。
required和optional沒有要求順序、可多次出現(xiàn)、可不添加,默認(rèn)為required

采用協(xié)議

當(dāng)類中實(shí)現(xiàn)了協(xié)議的方法時(shí),使用如下方式采用協(xié)議:

@interface ClassName : SuperClassName <協(xié)議名>

@end

其中在協(xié)議中聲明為required的方法必須實(shí)現(xiàn),否則會出現(xiàn)警告;在協(xié)議中聲明為optional的方法可視具體情況選擇實(shí)現(xiàn)。

一個(gè)類中可同時(shí)采用多個(gè)協(xié)議,書寫方式如下:

@interface ClassName : SuperClassName <協(xié)議名1, 協(xié)議名2, 協(xié)議名3>

@end

也可以在Category中實(shí)現(xiàn)協(xié)議,此時(shí)在Category中聲明采用協(xié)議:

@interface ClassName (CategoryName) <協(xié)議名1, 協(xié)議名2, 協(xié)議名3>

@end

還可以在類的擴(kuò)展中聲明采用協(xié)議:

@interface ClassName () <協(xié)議名>
@end

繼承協(xié)議

協(xié)議可以繼承,在某個(gè)協(xié)議中可以追加新的方法來生成新的協(xié)議。新協(xié)議的聲明如下

@protocol 協(xié)議名 <父協(xié)議名>
@required
聲明方法
@optional
聲明方法
@end

協(xié)議的類型聲明

聲明一個(gè)對象使用于某個(gè)協(xié)議:

id <協(xié)議名> obj;

對象也可以是臨時(shí)參數(shù):

- (void)method:(id<協(xié)議名>)param;

協(xié)議前置聲明

如果只在頭文件中使用協(xié)議名,為了加快編譯速度可以指定前向引用。這與類的前置聲明是一樣。

@protocol 協(xié)議名;

檢查是否采用協(xié)議

在程序運(yùn)行中可檢查對象是否采用某個(gè)協(xié)議。使用@protocol()來獲取協(xié)議數(shù)據(jù)指針。

//檢查類是否采用協(xié)議
+ (BOOL)conformsToProtocol:(Protocol *)aProtocol; 

//檢查對象是否采用協(xié)議
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;

例如,要檢查對象是否采用某個(gè)協(xié)議,可以這樣

if ([obj conformsToProtocol:@Protocol(協(xié)議名)])

類的多重繼承

在Objective-C中定義的類只有一個(gè)父類,有的編程語言(例如C++)也可以指定多個(gè)父類。能繼承多個(gè)父類的方式成為多重繼承。
Objective-C沒有多重繼承,但使用協(xié)議也能實(shí)現(xiàn)同等功能。比起多重繼承,協(xié)議即靈活又清晰。

非正式協(xié)議(informal protocol)

好吧,前面說了那么多,其實(shí)都是很基礎(chǔ)的東西,本文的主要目的也是為了表述清楚非正式協(xié)議這個(gè)概念。

非正式協(xié)議的概念

非正式協(xié)議其實(shí)就是將一些方法聲明為NSObject的Category。它只是做了聲明,而并沒有實(shí)現(xiàn)。在使用中要檢查非正式協(xié)議的是否已實(shí)現(xiàn),只能對每個(gè)方法調(diào)用respondsToSelector:。

非正式協(xié)議有以下特點(diǎn):

  • 非正式協(xié)議被聲明為NSObject的Category;
  • 非正式協(xié)議中聲明的方法不一定要實(shí)現(xiàn)
  • 編譯時(shí)不能檢查類對非正式協(xié)議的適用性
  • 運(yùn)行時(shí)不能檢查類對非正式協(xié)議的適用性,只能檢查是否實(shí)現(xiàn)了每個(gè)方法

非正式協(xié)議的用途

在Cocoa中,從系統(tǒng)方調(diào)用用戶編程方的對象來互發(fā)消息時(shí),經(jīng)常用到非正式協(xié)議。
例如,Application框架的類NSColorPanel中定義了非正式協(xié)議(AppKit/NSColorPanel)。

@interface NSObject (NSColorPanelResponderMethod)
- (void)changeColor:(id)sender;
@end

在調(diào)色板改變顏色時(shí),界面上選擇的對象如果實(shí)現(xiàn)了這個(gè)方法,就可以接受到消息執(zhí)行改變顏色的處理。而如果沒實(shí)現(xiàn)該方法,則不會接受這個(gè)消息。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容