Objective-C 程式設計 第十一章
分類和協議
通過分類以模組的形式向類新增方法。以及如何建立標準化的方法列表提供給他人實現。
分類
給已知類新增功能時,可以考慮新建子類,並實現新方法,使用子類。
更簡單的辦法,分類。
分類,可以將類的定義模組化到相關方法的組或分類中。
它還提供了擴充套件現有類的簡便方式,並且不必訪問類的原始碼,也無須建立子類。
語法:
類似於建立一個類。
區別在於: @interface Fraction (MathOps)
這就是建立了一個Fraction的分類MathOps
實現部分可以放在一個實現部分,也可以單獨放在一個檔案。
@implementation Fraction (MathOps)
檔名稱可以考慮Fraction+MathOps.h
如果將分類放到一個主類定義檔案中,那麼這個類的所有使用者都將訪問這個分類中的方法。
如果不能直接修改原檔案,那就只能選擇單獨儲存分類。
類的擴充套件
無名分類。
在定義分類時(), 中不寫名字。
定義一個像這樣的無名分類時,可以使用額外的例項變數和屬性來擴充套件類。只有無名分類可以這樣做。
無名分類中宣告的方法需要在主實現區域實現。
無名分類非常有用,因為它們的方法都是私有的。如果想將一個方法做成私有的,可以將其放入無名分類。
注意:方法沒有在介面部分登記,在這個意義上它們是私有的。然而,如果你知道私有方法的名字,那麼也可以呼叫它。
在實現部分:
@interface Fraction ()
- (void) reduce;
@end
關於分類的注意事項
分類可以覆寫該類中的另一個方法,但是很不建議這麼做。
1. 覆寫之後,再也不能訪問之前的方法。如果確實需要覆寫的話,使用子類來覆寫。可以使用super來訪問父類的方法。
通過使用分類新增新方法來擴充套件類不僅會影響這個類,同時會影響它的所有子類。
同樣,物件/分類命名對必須是唯一的。因為Objective-C名稱空間是程式程式碼與所有的庫、框架和外掛共享的。
協議和代理
協議是多個類共享的一個方法列表。
協議列出了一組方法,有些可以選擇實現,有些必須實現。如果採用該協議,就需要遵守。
語法:
@protocol NSCoping
- (id) copyWithZone: (NSZone *)zone;
@end
如果某個類採用某個協議,語法如下:
@interface AddressBook: NSObject <NSCoping>,編譯器期望找到AddressBook實現部分的copyWithZone的實現。
如果有多個協議,使用逗號隔開。 <A, B>
如果你定義了自己的協議,那麼不必自己實現它。可以告訴別人,如果採用這個協議,則必須實現這些方法。
這些方法可以從超類繼承。
如果父類遵守NSCoping協議,那麼它的子類也遵守NSCoping,但有可能子類需要自己定製實現。
@protocol NSCoping
- (id) copyWithZone: (NSZone *)zone;
@optionnal
- (void) outline;
@end
optionnal,可以標識選擇性實現的方法。@optionnal,可以標識選擇性實現的方法。
required,可以列出需要的方法。
注意,協議不引用任何類,它是無類的。
可以使用conformsToProtocol方法檢查一個物件是否遵循某項協議。
id obj1;
if ([obj1 conforsToProtocol: @protocol (Drawing)] == YES)
{}
可以使用respondsToSelector測試是否實現了可選的outline方法。
id <Drawing> obj1; 多條協議使用逗號。
通過在型別名稱之後的尖括號中新增協議名稱,藉助編譯器來檢查變數的一致性。
如果給obj1賦值的物件並不遵守Drawing協議,則會警告。
@protocol Drawing3D <Drawing>
可以擴充套件協議。表示Drawing3D首先遵守Drawing。
分類也可以遵守某些協議。也可以在實現部分使用無名分類()來進行擴充套件協議。
代理
協議也是一種兩個類之間的藉口定義。定義了協議的類可以看作是將協議定義的方法代理給了實現它們的類。
這樣,類的定義可以更為通用,因為具體的動作由代理類來承擔,響應某些事件或者定義某些引數。
非正式協議,看起來像一個分類。列出了一些方法,而沒有實現它們。
非正式協議通常是為根類定義的。有時也被稱為抽象協議。
它實際上僅僅是一個名稱下的一組方法,在文件說明和模組化方法時,可能有所幫助。
可以使用optional 取代這個非正式協議。
合成物件。
實際是使用組合的方式包裝出來一個適合需求的類。