第12章 類別
利用Objective-C的動態運行時分配機制,可以爲現有的類添加新方法,這些新方法在Objective-C裏被稱爲類別(category)
12.1 創建類別
文件命名:“類名稱”+“類別名稱”
12.1.2 @interface 部分
@interface NSString(NumberConvenience)
-(NSNumber *)lengthAsNumber;
@end
可以在類別中添加屬性,但不能添加實例變量,而且屬性必須是@dynamic類型的。
12.1.3 @implementation部分
@implementation NSString(NumberConvenience)
-(NSNumber *)lengthAsNumber
{
NSUInteger length = [self length];
return ([NSNumber numberWithUnsignedInt : length]);
} //lengthAsNumber
@end //NumberConvenience
12.1.4 類別的缺陷
有兩方面侷限性:
- 無法向類中添加新的實例變量,類別沒有位置容納實例變量
- 名稱衝突,即當類別中的方法與原始類方法名稱衝突時,類別具有更高的優先級。類別方法將完全取代初始方法從而無法再使用初始方法。
12.1.5 類別的優勢
類別主要有 3個作用:
- 將類的實現分散到多個不同文件或多個不同框架中
- 創建對私有方法的前向引用
- 向對象添加非正式協議
12.1.6 類擴展(class extension)
一種特殊的類別,其特點是:
- 不需要名字
- 可以在包含自己的源代碼的類(即自定義的類)中使用它
- 可以添加實例變量
- 屬性可以是可讀寫的
- 創建的數量不限
12.2 利用類別分散實現代碼
利用類別可以將實現代碼分散。
比如NSString的類別NSStringDrawing允許向字符串發送繪圖消息。
12.3 利用類別創建前向引用
Cocoa沒有真正的私有方法。如果知道對象支持的某個方法的名稱,即使該對象所在的類的接口中沒有聲明該方法,也可以調用它。
如果編譯器發現你調用對象的某個方法,但卻沒有找到該方法的聲明或定義,編譯器會發出警告。
這時使用類別,在類別中聲明這些方法(不必提供方法實現),編譯器就不會再產生警告。
12.4 委託、非正式協議、正式協議
協議(Protocol)wiki
協議是一組沒有實現的方法列表,任何的類均可採納協議並具體實現這組方法。
協議類似於Java與C#語言中的“接口。在Objective-C中,有兩種定義協議的方式:由編譯器保證的“正式協議”,以及爲特定目的設定的“非正式協議”。
非正式協議爲一個可以選擇性實現的一系列方法列表。非正式協議雖名爲協議,但實際上是掛於NSObject上的未實現分類(Unimplemented Category)的一種稱謂,Objetive-C語言機制上並沒有非正式協議這種東西,OSX 10.6版本之後由於引入@optional關鍵字,使得正式協議已具備同樣的能力,所以非正式協議已經被廢棄不再使用。
正式協議類似於Java中的”接口”,它是一系列方法的列表,任何類都可以聲明自身實現了某個協議。在Objective-C 2.0之前,一個類必須實現它聲明匹配的協議中的所有方法,否則編譯器會報告錯誤,表明這個類沒有實現它聲明匹配的協議中的全部方法。Objective-C 2.0版本允許標記協議中某些方法爲可選的(Optional),這樣編譯器就不會強制實現這些可選的方法。
協議經常應用於Cocoa中的委託及事件觸發。例如文本框類通常會包括一個委託(delegate)對象,該對象可以實現一個協議,該協議中可能包含一個實現文字輸入的自動完成方法。若這個委託對象實現了這個方法,那麼文本框類就會在適當的時候觸發自動完成事件,並調用這個方法用於自動完成功能。
Objective-C中協議的概念與Java中接口的概念並不完全相同,即一個類可以在不聲明它匹配某個協議的情況下,實現這個協議所包含的方法,也即實質上匹配這個協議,而這種差別對外部代碼而言是不可見的。正式協議的聲明不提供實現,它只是簡單地表明匹配該協議的類實現了該協議的方法,保證調用端可以安全調用方法。