I have a series of \"policy\" objects which I thought would be convenient to implement as class methods on a set of policy classes. I have specified a protocol for this, and
A class in Objective-C does work like an instance -- the main underlying difference is that retain counting does nothing on them. However, what you're storing in the -availableCounters array aren't instances (the id
type) but classes, which have a type of Class
. Therefore, with the -availableCounters definition you specified above, what you need is this:
Class counterClass = [[MyModel availableCounters] objectAtIndex: self.index];
return ( [counterClass countFor: self] );
However, it would probably be semantically better if you used instances rather than classes. In that case, you could do something like the following:
@protocol Counter
- (NSUInteger) countFor: (Model *) model;
@end
@interface CurrentListCounter : NSObject<Counter>
@end
@interface SomeOtherCounter : NSObject<Counter>
@end
Then your model class could implement the following:
static NSArray * globalCounterList = nil;
+ (void) initialize
{
if ( self != [Model class] )
return;
globalCounterList = [[NSArray alloc] initWithObjects: [[[CurrentListCounter alloc] init] autorelease], [[[SomeOtherCounter alloc] init] autorelease], nil];
}
+ (NSArray *) availableCounters
{
return ( globalCounterList );
}
Then your use of that would be exactly as you specified above:
id<Counter> counter = [[Model availableCounters] objectAtIndex: self.index];
return ( [counter countFor: self] );
It turns out it is actually working and the warning is incorrect.
So the question still stands as to whether its a reasonable thing to do (use class methods if they don't need any state)?
And how to best handle the warning (I like to run warning free)?
My only workaround was to have a second protocol (essentially the same as the first but declare it on the instance side):
@protocol CounterInstance
-(NSInteger) countFor: (Model *)model;
@end
And where I access the counters use it instead (to trick the compiler):
id<CounterInstance> counter = [[MyModel availableCounters] objectAtIndex: self.index];
return [counter countFor: self];
Its a bit awkward but does work. Am interested in views from others?
This
id <Counter> counter = [[Model availableCounters] objectAtIndex:0];
return ( [counter countFor: nil] );
Should be
Class <Counter> counter = [[Model availableCounters] objectAtIndex:0];
return ( [counter countFor: nil] );
In the first you have an instance that conforms to <Counter>
. In the second you have a class that conforms to <Counter>
. The compiler warning is correct because instances that conform to <Counter>
don't respond to countFor:
, only classes do.