1

How do you decorate a class with some generic implementation of a protocol?

Sorry for what might be an obvious question. I'm new to objective c and so am still treading water just a little bit.

I've got a protocol for which I want a generic implementation:

@protocol SelectableElement <NSObject>
@property BOOL selected;
@end

I've got a couple of objects that I want to be selectable:

@interface Widget : NSObject <SelectableElement>
@end

@interface Duhicky : NSObject <SelectableElement>
@end

What I'd like to do is to write the implementation of the protocol once, and make sure that both objects implement it that way.

I don't think that I can write a generic category and bind it to both, so I guess one way of doing it is to add implement the category on the common class NSObject:

@implementation NSObject (Selectable)
- (BOOL)selectable
{
    if (![self conformsToProtocol:@protocol(SelectableElement)]) return;

    return YES; // Use associative storage for this?
}

- (void)setSelectable:(BOOL)selectable
{
    if (![self conformsToProtocol:@protocol(SelectableElement)]) return;

    // set this associatively?
}
@end

Of course, I can't define a property variable to do this, I would need to use the associative object store... which I've not demonstrated here.

Is this the only way of adding selectable behaviour generically to anything that implements the selectable element protocol? Or is there a more obvious way that I'm missing?

I can of course use inheritance to implement this simple example, but that would only work for implementing a single protocol in this way. Is this approach that I've suggested considered a natural fit, or is it a hack?

Joe

Dr Joe
  • 718
  • 5
  • 19

3 Answers3

1

Make a class that implements the protocol ie. SelectableObject and then make the Widget and Duhicky classes inherit SelectableObject.

graver
  • 15,183
  • 4
  • 46
  • 62
0

It sounds you want something like a Mixin in Ruby. Unfortunately, this is not possible on the language level in Objective-C. The only way to share behaviour is through inheritance.

That said, you could do some tricks with the Objective-C runtime to achieve what you want. It's probably not a good idea to work against the language you're using, but if you want to explore this option have a look here: http://cocoadev.com/wiki/MethodSwizzling

Erik Doernenburg
  • 2,933
  • 18
  • 21
0

Sadly, this is one of those cases where inheritance is a particularly bad fit for the problem.

However, you can see this (ab)use of inheritance in the Cocoa frameworks (NSResponder or UIResponder). You'll run up against problems if you need to make an object selectable if you don't control the inheritance structure (some object in an external framework).

Your category on NSObject will work, and I would consider it preferable in this case. At first glance it seems heavy-handed for every object to carry around these methods, but the performance penalty is small due to caching in the method lookup mechanism.

Community
  • 1
  • 1
joerick
  • 16,078
  • 4
  • 53
  • 57