类组合如何在iOS中运行?

时间:2012-03-14 21:16:50

标签: objective-c ios composition

假设A上的classA属性B上有属性classB,我希望classAB同时拥有属性AB {{1}}。我仍然不明白如何使用组合来完成所有工作。

我意识到这可以通过继承完成,但我想学习如何使用 composition 来完成此操作。我看了一些例子,但我仍然不知道它是如何运作的。

2 个答案:

答案 0 :(得分:21)

创建一个新类,它具有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中执行的一件事是捕获发送到您的对象的消息,这些消息没有关联的方法,并将它们转发给另一个对象。如果您正在编写一个将作为另一个类构成的类,或者如果要转发许多不同的消息并且您不想手动将它们全部写出来,这个技巧很有用。

使用邮件转发的缺点是您放弃了某些控制,并且在您的类或转发类处理邮件时,可能更难预测。例如,如果超类实现了一个方法,那么将执行该方法,并且不会调用转发代码。

答案 1 :(得分:8)

假设ClassAClassB已按照您的说法实施,这非常有效,并且可以轻松扩展。

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