Target C protocols that require implementation of at least one of the many methods

Objective-C may require or optional protocol methods:

@protocol AProtocol @required -(void) aRequiredMethod; @optional -(void) anOptionalMethod; @end 

Is there an elegant way to say that an object that matches the protocol must respond to at least one of the many methods, my dream will be something like

 @protocol AProtocol @anyof -(void) onePossibleMethod; -(void) anotherPossibleMethod; @optional -(void) anOptionalMethod; @end 

EDIT:

This (as far as I know) is impossible, there would be a way to increase compilation warning time if a class declared as conforming to this protocol, consisting entirely of optional methods

 @protocol AProtocol @optional -(void) onePossibleMethod; -(void) anotherPossibleMethod; @end 

failed to implement at least one of them.

+7
source share
3 answers

It is impossible to express this in Objective-C. If you have to do this, IMO - the most idiomatic and least dangerous for code - is something like that:

 @protocol AProtocol @required - (SEL)methodToUse; // returns one of "onePossibleMethod" or "anotherPossibleMethod" @optional -(void) onePossibleMethod; -(void) anotherPossibleMethod; -(void) anOptionalMethod; @en 
+3
source

Well, you are working with ObjC, so you will need to exercise some restraint:

 @protocol MONAbstractDataProvider @optional - (void)anOptionalMethod; @end @protocol MONDataProviderA < MONAbstractProvider > @required - (void)onePossibleMethod; @end @protocol MONDataProviderB < MONAbstractProvider > @required - (void)anotherPossibleMethod; @end 

In this case, you will need to run the confromsToProtocol: test on the callsite site, not the respondsToSelector: test for onePossibleMethod and anotherPossibleMethod . Then you pass MONAbstractDataProvider around. This may introduce some type safety if you remember the rules, but it is really a little better than the usual approach.

Thus, the client side will look like this:

 - (void)update:(NSObject<MONAbstractDataProvider>*)provider { if ([provider conformsToProtocol:@protocol(MONDataProviderA)]) { [(NSObject<MONDataProviderA>*)protocol onePossibleMethod]; } else if ([provider conformsToProtocol:@protocol(MONDataProviderB)]) { [(NSObject<MONDataProviderB>*)provider anotherPossibleMethod]; } else { assert(0 && "rule broken"); } } 

This, of course, assumes that the client is aware of all derivatives.

Instead, you can choose a simpler singular approach if they are both void :

 @protocol MONAbstractDataProvider @required - (void)performPossibleMethod; @optional - (void)anOptionalMethod; @end 
+3
source

You can have a dynamic delegation property that allows a delegate to be assigned only to classes that implement one or the other method, but this will be at runtime, and not at compile time. You can also create a bash script that will check if one or the other has been implemented and which would be at compile time.

0
source

All Articles