objective c - programacion - ¿Cómo funciona la composición de clases en iOS?
relaciones entre clases programacion orientada a objetos (2)
Digamos que tengo la propiedad A
en classA
y la propiedad B
en classB
y quiero que classAB
tenga ambas propiedades A
y B
Todavía no entiendo cómo hacer que todo esto funcione con la composición .
Me doy cuenta de que esto se puede hacer con herencia, pero quiero aprender a hacer esto con la composición . He visto ejemplos y todavía no entiendo cómo funciona todo.
Crea una nueva clase, que tiene instancias de classA y classB como variables miembro. Luego implementas las propiedades pasando a través de los métodos get / set.
@interface ClassAB
{
ClassA *objectA;
ClassB *objectB;
}
@property (nonatomic,strong) id propertyA;
@property (nonatomic,strong) id propertyB;
@end
@implementation ClassAB
- (id)propertyA { return objectA.propertyA; }
- (void)setPropertyA:(id)value { objectA.propertyA = value; }
- (id)propertyB { return objectB.propertyB; }
- (void)setPropertyB:(id)value { objectB.propertyB = value; }
@end
Y eso es lo que es la composición. Algunos idiomas tienen una sintaxis especial para hacer esto (por ejemplo, en Ruby puedes incluir un conjunto de métodos de una clase / módulo en otra), pero Objective-C no lo permite.
Una cosa que puede hacer en Objective-C es capturar los mensajes enviados a su objeto que no tienen un método asociado y reenviarlos a otro objeto. Este truco es útil si está escribiendo una clase que se presentará como otra clase, o si hay muchos mensajes diferentes para reenviar y no desea escribirlos todos manualmente.
La desventaja de usar el reenvío de mensajes es que renuncia a un poco de control y puede ser más difícil predecir cuándo un mensaje será manejado por su clase o la clase de reenvío. Por ejemplo, si una superclase implementa un método, ese método se ejecutará y el código de reenvío no se llamará.
Suponiendo que ClassA
y ClassB
se implementan como usted dijo, esto funciona muy bien y es fácilmente extensible.
@interface ClassAB : NSObject
@property int a;
@property int b;
@property ClassA *aObject;
@property ClassB *bObject;
@end
@implementation ClassAB
@dynamic a, b;
@synthesize aObject, bObject;
-(id) forwardingTargetForSelector:(SEL)aSelector
{
if ([aObject respondsToSelector:aSelector])
return aObject;
else if ([bObject respondsToSelector:aSelector])
return bObject;
return nil;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
ClassA *a = [ClassA new];
ClassB *b = [ClassB new];
ClassAB *ab = [ClassAB new];
ab.aObject = a;
ab.bObject = b;
ab.a = 10;
ab.b = 20;
NSLog(@"%i, %i", a.a, b.b); // outputs 10, 20
}
return 0;
}