Object-C Categories和Protocols

Categoryjava

要擴展一個不可修改的類,一般的作法是爲該類建立一個子類,在子類中實現想要實現的方法,在Object-C中,能夠經過category來實現,而且實現方式更爲簡單。框架

如今有以下定義:一個包含4個方法的Fraction類ui

1 @interface Fraction : NSObject
2 @property int num, den;
3 
4 -(void) setTo:(int) n over:(int) d;
5 -(void) reduce;
6 -(double) converToNum;
7 -(void) print;
8 @end

如今要爲該類增長4個方法,分別爲加法、減法、乘法和除法:spa

 1 // 定義category文件:FractionMathOps.h文件
 2 // 因爲category是擴展文件,全部首先須要引入原文件
 3 #import "Fraction.h"
 4 
 5 @interface Fraction (MathOps)
 6 -(Fraction *) add: (Fraction *) f;
 7 -(Fraction *) mul: (Fraction *) f;
 8 -(Fraction *) sub: (Fraction *) f;
 9 -(Fraction *) div: (Fraction *) f;
10 @end
11 
12 // 可選的將implementation定義在interface文件中,或者定義在單獨的FractionMathOps.m文件中
13 @implementation Fraction (MathOps)
14 -(Fraction *) add : (Fraction *) f
15 {
16     ....
17 }
18 ....
19 @end

經過上述方法定義的category不能爲原類追加成員變量,若須要追加成員變量,在定義category時不能填寫名字,如:code

 1 #import "Fraction.h"
 2 
 3 @interface Fraction ()
 4 @property int uniqueID;
 5 
 6 -(void) doStuffWithUniqueID: (int) theID;
 7 @end
 8 
 9 // -------------------------------------------------------
10 
11 // implementation實現部分,注意,Fraction後面沒有括號()
12 @implementation Fraction
13 @synthesize uniqueID;
14 
15 -(void) doStuffWithUniqueID: (int) theID
16 {
17     ...
18 }
19 @end

經過這種方法爲類追加的全部方法都是private屬性的,因此只但願類本事使用這些方法,這是一個好辦法。orm

若使用category追加原類中已經方法時,原類中的方法會被覆蓋,且沒法調用原類中的方法。對象

能夠爲一個類建立多個category,若多個category文件中定義了同一個方法,Object-C沒法肯定具體會調用那個方法。blog

同時須要注意,爲一個類添加category,受影響的不單單是該類,也包括該類的子類在內。繼承

Protocols和Delegation接口

Protocol是指一系列可在多個類中共享的方法,這些方法並無特定的implementation去實現,其實就是java中的接口。

protocol中的方法有些能夠選擇性的實現,有些則必須被實現

定義protocol,只須要使用@protocol,後面接protocol的名字,以後開始像在interface中聲明方法那樣聲明protocol方法,全部方法聲明之後,以@end結尾。

在Foundation框架中,

1 @protocol NSCopying
2 - (void)copyWithZone: (NSZone *)zone;
3 @end 

定義一個是否須要必須被實現的方法:@required和@optional,默認爲@required。

@protocol MyProtocol
@required // 該命令能夠省略
- (void) print1; // 必須被實現
@optional 
- (void) print2; // 能夠不被實現
@end

一個類若要實現一個或多個protocol,只需將protocolName放到尖括號"<>"中追加到@interface後面既可,多個protocols之間使用逗號","分割。

1 @interface MyObj: NSObject <NSCopying>

 在上述代碼中,因爲系統已經知道了NSCopying的定義,因此無需在interface中定義NSCopying protocol。

若一個類實現了一個或多個protocol,該類的子類一樣會實現這些protocols

可使用conformsToProtocol:方法去判斷一個對象是否實現了指定的protocol,如:

1 id currentObj;
2 ...
3 if ([currentObj conformsToProtocol: @protocol (Drawing)] == YES)
4 {
5     ...
6 }

在上述代碼中,經過使用@protocol (protocolName)的方式產生一個protocol對象 

1 // 聲明一個必須實現Drawing protocol的類實例
2 // 若currentObj類中沒有實現給protocol,則編譯器會發出警告信息
3 id <Drawing> currentObj;

定義一個protocol時,能夠指定該protocol繼承另外一個protocol:

1 // MyPro1 繼承MyPro
2 // 此時實現MyPro1的類也必須實現MyPro中必需要被實現的方法
3 @protocol MyPro1 <MyPro>
4 ...
5 @end

在category中實現protocol

1 @interface MyObj (stuff) <MyPro>
2 ...
3 @end

能夠將MyPro的實現放到stuff中

1 Fraction *frac=[[Fraction alloc] initWithNumerator: 3 denominator: 5];
2 <Printing1> p1=frac;
3 [p1 print1];
4 id<Printing1,Printing2,Printing3> p2=frac;
5 [p2 print2];
6 [p2 print3];
相關文章
相關標籤/搜索