協議和分類

2021-06-23 04:42:01 字數 3503 閱讀 6214

通過建立category可以為現有

的類新增新方法。為什麼不

派生子類

?因為objective-c中

有很多類本質是類簇,為這樣

的類建立子類會很困難。或者我們可以建立子類,但**中正在使用

的某些工具集或庫可能無法處理新子類

的物件。

使用category可以為任何類新增新的方法,甚至那些沒有源**的類。

1,使用分類(category)以模組的方式向類新增方法.

2,建立標準化的方法類表供其他人實現.

11.1:分類

使用場景:

1,有時候在處理類定義時,可能想要為其新增一些新方法.

2,假如你參與了乙個大型程式設計專案,並且作為專案的一部分,正在定義乙個新類,新類中包含許多方法.你的任務是:為該類編寫處理檔案系統的方法.其他專案成員的任務負責以下方法:建立和初始化該類例項,對該類中的物件執行操作以及在螢幕上繪製該類物件的表示.

3,假如你已經知道如何使庫中的類(例如fundation的陣列類,nsarray),並且意識到你希望該類實現了乙個或者多個方法.當然,你可以編寫nsarray類的新子類並實現新方法.

針對以上所有情況的使用的解決方案可以用:分類.

分類提供了一種簡單的方式,用它可以將類的定義模組化到 相關方法的組或者分類中.分類還提供了一種擴充套件現有類定義的簡便方式,並且不必訪問類的源**.也無需建立子類.

fraction原始**

#import 

//define the fraction class

@inte***ce fraction : nsobject

//將例項變數轉換為屬性

@property 

intnumerator,denominator; 

//定義例項方法 -(

void

) setto: (

int) n over: (

int) d; 

-(fraction *) add: (fraction *) fraction;  -(

void

) reduce;  -(

double

) converttonumber;  -(

void

) print; 

@end; 

#import "fraction.h"

#inte***ce fraction (mathops)

-(fraction *) add: (fraction *) f; 

-(fraction *) mul: (fraction *) f; 

-(fraction *) sub: (fraction *) f; 

-(fraction *) div: (fraction *) f; 

@end;  

#inte***ce fraction(mathops):這句**告訴編譯器你正在為fraction編寫新的分類.而且新的分類的名稱是mathops.在這裡沒有列出實 例變數,因為在以前定義的介面部分中已經這樣做了.實際上如果再次列出的話,將接收到編譯器發出的語法錯誤.

以上擴充套件介面的作用是:告訴編譯器,你正在mathops分類下為名為fraction類新增擴充套件.

可以將所有方法的定義放在乙個實現部分,也就是,可以在乙個實現檔案中定義fraction.h介面中的所有方法和 mathops分類中的所有方法.也可以在單獨的實現部分定義分類的方法.在第二種情況下,這些方法的實現部分還必須找出方法所屬的分類.和介面部分一 樣,通過將類名稱擴在類名稱之後的圓括號內類確定方法所屬的分類.

@implementation fraction(mathops) 

//code for category methods

@end; 

關於分類的一些注意事項:

1.儘管分類可以訪問原始類的例項變數,但是它不能新增自身的實力變數,如果需要新增變數,可以考慮建立子類.

2.分類可以過載類中的另乙個方法,但是通常不這樣做,這種做法是拙劣的設計習慣.過載了乙個方法之後,再也不能訪問原來的方法.

3.可以擁有多個分類,如果乙個方法定義在多個分類中,該語句不會執行指定使用哪個分類.

4,和一般介面不同的是,不必實現分類中的所有方法.

5.通過使用分類新增新方法來擴充套件不僅會影響這個類,還會影響其所有子類.

11.2:協議:

協議是多個類共享乙個方法列表.協議中列出的類沒有響應的實現,有其他人來實現.

協議使用指定的名稱定義一組多少有點相關的方法.這些方法通常有文件說明.所以你知道他們將如何執行.因此如果需要,可以在自己的類中定義他們的實現.

如果決定實現特定協議的所有方法,也就意味著要遵守這項協議.

定義乙個協議:下面是乙個例子

@protocol nscopying 

- (id)copywithzone: (nszone *) zone; 

@end;

如果你的類採用了nscopy協議,則必須遵守實現名為copywithzone的方法.通過在@inte***ce行的一對<>內列出協議名

可以告訴編譯器你正在使用乙個協議.這項協議的名稱放在類名和它的父類名稱之後.

@inte***ce addressbook: nsobject 如果你的類實現了多項協議,協議之間用逗號分開.

協議不引用任何型別,它是無類的.任何類都可以遵守drawing協議.

可以使用conformstoprotocal:方法檢查乙個物件是否遵守某項協議.

例如有乙個名為currentobject的物件,並且想要檢視它時候是遵循drawing協議.可以向他放鬆繪圖訊息

id currentobjec; 

([currentobjec : conformstoprotocal:

@protoco (drawing) : == yes])

這裡使用乙個專用的@protocol指令用於獲取乙個協議名稱.並產生乙個protocol物件.

通常在型別名稱之後的<>中新增協議名稱,可以借助編譯器來檢查變數的一致性.id currentobject;

這告訴編譯器currentobject將包含遵守drawing協議的物件.如果這個物件遵循多個協議,可以用逗號隔開.

定義一項協議的時候,可以擴充套件現有的協議.

@protocol drawwing3d 說明drawwing3d協議也使用了drawing協議.

最後分類也可以採用一項協議

@inte***ce fraction (stuff)

此處fraction類擁有乙個stuff分類,這個分類採用了nscopy,nscoding兩個協議.

和類名稱一樣,協議名稱也是唯一的.

然後,從介面部分刪除add:方法,並將其新增到新分類,同時新增其他三種要實現的數**算.新mathops分類的介面部分應該如下所示.

注意:這既是介面部分的定義,也是現有介面部分的擴充套件.因此必須包括原始介面部分.這樣編譯器就知道fraction類.

daytime協議和時間協議

有乙個有用的除錯工具就是daytime服務。它的作用就是返回當前時間和日期,格式是字串格式。daytime服務是基於tcp的應用,伺服器在tcp埠13偵聽,一旦有連線建立就返回ascii形式的日期和時間,在傳送完後關閉連線。接收到的資料被忽略。daytime服務也可以使用udp協議,它的埠也是13,...

SLIP協議和PPP協議

slip 協議和ppp協議都是資料鏈路層協議。slip和ppp是序列線上最常用的兩個鏈路層通訊協議,它們為在點對點鏈路上直接相連的兩個裝置之間提供一種傳送資料報的方法。互聯的兩端裝置可以是主機與主機 路由器和路由器 主機和路由器。slip 協議 序列線路網際協議slip serial line in...

SLIP協議和PPP協議

slip協議和ppp協議都是資料鏈路層協議。slip和ppp是序列線上最常用的兩個鏈路層通訊協議,它們為在點對點鏈路上直接相連的兩個裝置之間提供一種傳送資料報的方法。互聯的兩端裝置可以是主機與主機 路由器和路由器 主機和路由器。slip協議 序列線路網際協議slip serial line inte...