Подтвердить что ты не робот

Как классная композиция работает в iOS?

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

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

4b9b3361

Ответ 1

Вы создаете новый класс, который имеет экземпляры 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, - это сообщения catch, отправленные на ваш объект, которые не имеют связанного с ними метода, и пересылают их другому объекту. Этот трюк полезен, если вы пишете класс, который будет представлять собой другой класс, или если есть много разных сообщений для пересылки, и вы не хотите записывать их вручную.

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

Ответ 2

Предполагая, что 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;
}