有沒有辦法以某種方式模擬類的行爲,而不是方法的實例變量?實例變量的類別擴展
我有一個ClassA
,我想保留它的名字後用新的方法和其他cllass的ivars(ClassB
)。 當然,我可以繼承ClassA
,但生成的類會有不同的名稱。
對於方法的補充,這不是問題 - 類別是一個很好的解決方案。
UPDATE:ClassA
用作文件所有者用於XIB,並且這些字段被擴展是IBOutlet
秒。所以我需要在構建階段。
有沒有辦法以某種方式模擬類的行爲,而不是方法的實例變量?實例變量的類別擴展
我有一個ClassA
,我想保留它的名字後用新的方法和其他cllass的ivars(ClassB
)。 當然,我可以繼承ClassA
,但生成的類會有不同的名稱。
對於方法的補充,這不是問題 - 類別是一個很好的解決方案。
UPDATE:ClassA
用作文件所有者用於XIB,並且這些字段被擴展是IBOutlet
秒。所以我需要在構建階段。
我已經調查了這個問題玩associative references(感謝Ole),方法靜態變量,方法swizzling,最後來到這個簡單的解決方案(沒有運行時的東西)。我只是簡單地使用「分類」類來返回一個指向派生類的指針,這當然可以包含額外的Ivars。這樣做我可以實現一個意想不到的好處:我可以撥打super
的班級方法,這在延伸類別時是不可能的。一類擴展的
實施例(測試):
ClassA的+ ClassB.h
@protocol _ClassB_Protocol
@optional // to avoid warnings
- (IBAction) onClick:(id)sender;
@property (nonatomic, retain) IBOutlet UIButton *aButton;
@end
@interface ClassA (_ClassA_Category) <_ClassB_Protocol>
@end
@interface ClassB: ClassA <_ClassB_Protocol> {
UIButton *aButton; // _ivar_ to add
}
@end
ClassA的+ ClassB.m
@implementation ClassA (_ClassA_Category)
// this will be called first on [ClassA alloc] or [ClassA allocWithZone:(NSZone *)zone]
+(id) alloc {
if ([self isEqual: [ClassA class]]) {
return [ClassB alloc];
} else {
return [super alloc];
}
}
@end
@implementation ClassB: ClassA
@synthesize aButton;
-(void) dealloc {
[aButton release];
[super dealloc]; // this is impossible for an ordinary category
}
- (void) onClick:(id)sender {
// some code here
}
@end
現在我們在同一時間:
ClassB
「擴展」 ClassA
(分類方式);ClassB
繼承ClassA
(ClassB
可以調用ClassA
方法);ClassB
可以通過ClassA
名稱來訪問(分類方式)由於iPhone使用了現代的Objective-C運行庫,因此您可以使用associative references向實例添加數據,而無需聲明實例變量。請參閱objc_setAssociatedObject
等文檔。
如果使用標準存取方法將調用包裝到運行時,它將非常易於使用。
用於運行時級別解決方案。但是,我使用`ClassA`作爲**文件所有者**作爲XIB,並且這些字段是`IBOutlets`。所以,我需要在構建階段。對不起,沒有指定這個細節。 – 2011-02-03 14:34:20
我把馬丁的例子爲一個平凡的應用程序與NSData的,ClassB的與XXData和的onClick與getIvar更換ClassA的,並調用它(的Mac OS X 10.6 。6時,Xcode 4最終)其中:
NSData * data = [NSData data];
NSLog(@"%@", [data getIvar]);
它失敗 「 - [NSConcreteData getIvar]:無法識別的選擇發送到實例」 ..
它失敗,因爲 「黃金」 在NSData的類別(返回指向派生類的指針)不被上面的代碼調用。如果明確地調用「alloc」,如:
NSData * data = [[NSData alloc] init];
NSLog(@"%@", [data getIvar]);
那麼一切都很好。
它有一個新的名字有什麼問題?如果你試圖破解類繼承,那麼可能有更好的方法來做你想做的事情! – deanWombourne 2011-02-03 14:12:24
@deanWombourne:請查看更新後的問題。有時候,我們需要不尋常的方法。 – 2011-02-03 14:38:12