沒有直接的語言支持,但您可以完成類似的消息轉發。假設你有特質類「Foo」和「Bar」,分別定義方法「-doFoo
」和「-doBar
」。你可以定義你的班級有特點,像這樣:
@interface MyClassWithTraits : NSObject {
NSMutableArray *traits;
}
@property (retain) NSMutableArray* traits;
-(void) addTrait:(NSObject*)traitObject;
@end
@implementation MyClassWithTraits
@synthesize traits;
-(id)init {
if (self = [super init]) {
self.traits = [NSMutableArray array];
}
return self;
}
-(void) addTrait:(NSObject*)traitObject {
[self.traits addObject:traitObject];
}
/* Here's the meat - we can use message forwarding to re-send any messages
that are unknown to MyClassWithTraits, if one of its trait objects does
respond to it.
*/
-(NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector {
// If this is a selector we handle ourself, let super handle this
if ([self respondsToSelector:aSelector])
return [super methodSignatureForSelector:aSelector];
// Look for a trait that handles it
else
for (NSObject *trait in self.traits)
if ([trait respondsToSelector:aSelector])
return [trait methodSignatureForSelector:aSelector];
// Nothing was found
return nil;
}
-(void) forwardInvocation:(NSInvocation*)anInvocation {
for (NSObject *trait in self.traits) {
if ([trait respondsToSelector:[anInvocation selector]]) {
[anInvocation invokeWithTarget:trait];
return;
}
}
// Nothing was found, so throw an exception
[self doesNotRecognizeSelector:[anInvocation selector]];
}
@end
現在,您可以創建MyClassWithTraits的實例,並添加你想要什麼「特質」的對象:
MyClassWithTraits *widget = [[MyClassWithTraits alloc] init];
[widget addTrait:[[[Foo alloc] init] autorelease]];
[widget addTrait:[[[Bar alloc] init] autorelease]];
你可以做在MyClassWithTraits'-init
方法中調用-addTrait:
,如果您希望該類的每個實例具有相同種類的特徵。或者,你可以像我在這裏做的那樣做,它可以讓你爲每個實例分配一組不同的特徵。
然後你就可以調用-doFoo
和-doBar
,好像他們是通過插件實現的,即使消息被轉發到其特點的一個對象:
[widget doFoo];
[widget doBar];
(編輯:添加錯誤處理。 )
護理解釋什麼特質與混入了?這些概念可能得到支持,但以不同的名稱知道。 – 2011-04-08 21:50:35
當然,讓我修改。 – Bill 2011-04-08 21:55:59
貌似有人在這裏實現了Obj-C特質:http://etoileos.com//news/archive/2011/07/12/1427/ – Bill 2011-07-12 19:08:59