How does class composition work in iOS?

半世苍凉 提交于 2019-11-30 11:24:20

You make a new class, which has instances of classA and classB as member variables. Then you implement the properties by passing through the get/set methods.

@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

And that's what composition is. Some languages have special syntax to do this (e.g., in Ruby you can include a set of methods from one class/module in another), but Objective-C doesn't allow this.

One thing you can do in Objective-C is catch messages sent to your object which do not have an associated method, and forward them to another object. This trick is useful if you are writing a class that will pose as another class, or if there are many different messages to forward and you don't want to write them all out manually.

The downside to using message forwarding is that you give up some control and it can be a harder to predict when a message will be handled by your class or the forwarding class. For example, if a superclass implements a method, that method will be executed and the forwarding code will not be called.

Assuming ClassA and ClassB are implemented as you said, this works very well, and is easily extendable.

@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;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!