Как работает композиция классов в iOS? - PullRequest
19 голосов
/ 15 марта 2012

Допустим, у меня есть свойство A для classA и свойство B для classB, и я хочу, чтобы classAB имел оба свойства A и B. Я до сих пор не понимаю, как заставить все это работать с составом .

Я понимаю, что это можно сделать с помощью наследования, но я хочу узнать, как это сделать с состав . Я посмотрел на примеры и до сих пор не понимаю, как все это работает.

Ответы [ 2 ]

21 голосов
/ 15 марта 2012

Вы создаете новый класс, в котором экземпляры classA и classB являются переменными-членами. Затем вы реализуете свойства, передавая методы 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

И вот что такое композиция. Некоторые языки имеют специальный синтаксис для этого (например, в Ruby вы можете включить набор методов из одного класса / модуля в другой), но Objective-C не позволяет этого.

Одна вещь, которую вы можете сделать в Objective-C, - это перехватывать сообщения, отправленные вашему объекту, которые не имеют связанного метода, и пересылать их другому объекту. Этот прием полезен, если вы пишете класс, который будет выдавать себя за другой класс, или если нужно отправить много разных сообщений, и вы не хотите записывать их все вручную.

Недостатком использования пересылки сообщений является то, что вы отказываетесь от некоторого контроля, и может быть сложнее предсказать, когда сообщение будет обработано вашим классом или классом пересылки. Например, если суперкласс реализует метод, этот метод будет выполнен и код пересылки не будет вызван.

8 голосов
/ 15 марта 2012

Если предположить, что ClassA и ClassB реализованы, как вы сказали, это работает очень хорошо и легко расширяется.

@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;
}
...