您的位置:首页 > 编程语言 > Go语言

【ObjC】@interface类名(categoryName)

2014-12-24 11:07 288 查看
刚了解ObjC不久,有看到类似下面代码

[cpp] view
plaincopy

@interface ClassName ( CategoryName )

// method declarations

@end

对应的头文件一般定义为下面的格式

[cpp] view
plaincopy

ClassName+CategoryName.h

查了下才知道这是所谓的ObjC的所谓类扩展的方法

OOP的精神之一,就是如果你想研發一台新款式的車子,你並不需要重新發明輪子,通常的做法會去繼承某個現有的”車子類別”,然後加上你要的功能跟屬性,改一改就變成一款新的車子可以來騙錢了。

不過有時候你想幫原來的類別加功能,但又不想動到原來的程式碼,例如你可能下載了某款功能超強的2D物理引擎程式碼,但因為某些小地方寫的不合你的需求,於是你便動手改原始碼來加功能。這當然沒問題,但萬一原作出新的版本,你要不就選擇維持自己原來的版本不update,不然就是update之後,你原來加在舊版本的程式碼得再重貼一次到新版

Objective-C裡有個叫做
category
的東西可以幫你在現有的類別加上新功能,這樣一來上面這個問題就可以搞定了。跟別的程式語言比較起來,category的觀念有點像是在Ruby的mixin或是Python的open
class,都是在不影響或修改原來的類別或模組的情況下去修改原有的功能。

舉個例子,因為NSObject是所有物件的源頭,但我想要加一個方法讓所有的子類別都可用(把要加的功能放在繼承階層的最源頭並不是好的設計,在這裡只是舉個例子而已)。程式碼這樣寫:
//
interface

@interface

NSObject(MySuperObject)

-(void)

printRetainCount;

+(void)

sayHello;

@end/

/
implementation

@implementation

NSObject(MySuperObject)

-(void)

printRetainCount

{

NSLog(@"The
retain count is %d",

[self

retainCount]);

}

+(void)

sayHello

{

NSLog(@"Hello
everybody!");

}

@end

這裡用的是在後面加個小括號以及category的名稱。要注意的是category只能加method(instance
method或是class method都行),沒辦法增加instance variable(其實也不是完全不行,只是可能要用一些怪招,不過如果要做到這種程度,是不是該考慮直接用一般的繼承就好?)。使用起來的樣子:

//
建立Book物件

Book

*b

=
[[Book

alloc]

init];

//
instance method from category

[b

printRetainCount];

//
用完放掉

[b
release];

//
class method from category

[Book

sayHello];

上面這段程式碼如果一般的情況下,在編譯階段就會跳出警告(認不得printRetainCount跟sayHello這兩個方法),硬是執行的話就會直接錯誤。但因為我們已經有了category的加持,所以執行結果會是:
The retain count is 1
Hello everybody!


因為category是在原來的類別裡加功能,所以你可能會想萬一原來的類別裡有個跟你的category同名的方法怎麼辦? 答案是,會以category的定義為主,也就是原來類別裡的那個方法就被你蓋掉了,當然這不見得是你想要的結果。所以通常這種方法擴充的,會建議可以在前面加個prefix,避免跟原來的方法有重複而造成不幸的結果

另外,前面有篇提到protocol的文章,也提到了
informal
protocol
,其實它就是一種依附在NSObject上,但是沒有把功能實作出來的category。一般的protocol必需乖乖實作所有@required的方法(在Objective-C 2.0以前全部預設都是@required),但在informal protocol並沒有強制規定全部都要實作出來。事實上,在Objective-C 2.0之後才在protocol裡加進來的@optional語法,就是打算用來取代informal protocol的,在比較新版本的SDK大多都是用標準的protocol在寫了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: