No hay compatibilidad directa con el idioma, pero puede lograr algo similar con el reenvío de mensajes. Digamos que tiene las clases de rasgos "Foo" y "Bar", que definen los métodos "-doFoo
" y "-doBar
", respectivamente. Se podría definir la clase de tener rasgos, como esto:
@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
Ahora, puede crear instancias de MyClassWithTraits, y añadir lo que sea "rasgo" objetos desea:
MyClassWithTraits *widget = [[MyClassWithTraits alloc] init];
[widget addTrait:[[[Foo alloc] init] autorelease]];
[widget addTrait:[[[Bar alloc] init] autorelease]];
que podría hacer estas llamadas al -addTrait:
en el método MyClassWithTraits '-init
, si desea que cada instancia de esa clase tenga el mismo tipo de rasgos. O bien, podría hacerlo como lo he hecho aquí, lo que le permite asignar un conjunto diferente de rasgos a cada instancia.
Y entonces se le puede llamar -doFoo
y -doBar
como si estuvieran implementados por flash, a pesar de que los mensajes están siendo enviados a uno de sus rasgos objetos:
[widget doFoo];
[widget doBar];
(Editar: gestión de errores añadido.)
Cuidado de explicar qué rasgos y mixins son? Los conceptos pueden ser compatibles, pero se conocen por un nombre diferente. –
Claro, déjame revisar. – Bill
Parece que alguien ha implementado los rasgos Obj-C aquí: http://etoileos.com//news/archive/2011/07/12/1427/ – Bill