Tim*_*imM 10 metaprogramming objective-c class-method
我有一系列"策略"对象,我认为这些对象可以作为一组策略类的类方法实现.我为此指定了一个协议,并创建了符合的类(如下所示)
@protocol Counter
+(NSInteger) countFor: (Model *)model;
@end
@interface CurrentListCounter : NSObject <Counter>
+(NSInteger) countFor: (Model *)model;
@end
Run Code Online (Sandbox Code Playgroud)
然后我有一个符合这个协议的类的数组(像CurrentListCounter那样)
+(NSArray *) availableCounters {
return [[[NSArray alloc] initWithObjects: [CurrentListCounter class], [AllListsCounter class], nil] autorelease];
}
Run Code Online (Sandbox Code Playgroud)
注意我是如何使用像对象这样的类(这可能是我的问题 - 在Smalltalk类中,对象就像其他所有 - 我不确定它们是否在Objective-C中?)
我确切的问题是,当我从数组中取出一个策略对象时,我想调用该方法:
id<Counter> counter = [[MyModel availableCounters] objectAtIndex: self.index];
return [counter countFor: self];
Run Code Online (Sandbox Code Playgroud)
我在return语句中得到一个警告 - 它表示-countFor:在协议中找不到(所以它假定它是一个实例方法,我想调用一个类方法).但是,由于我的数组中的对象是类的实例,它们现在就像实例方法(或者概念上它们应该是).
有没有一种神奇的方法来调用类方法?或者这只是一个坏主意,我应该只创建我的策略对象的实例(而不是使用类方法)?
Jon*_*ess 20
这个
id <Counter> counter = [[Model availableCounters] objectAtIndex:0];
return ( [counter countFor: nil] );
Run Code Online (Sandbox Code Playgroud)
应该
Class <Counter> counter = [[Model availableCounters] objectAtIndex:0];
return ( [counter countFor: nil] );
Run Code Online (Sandbox Code Playgroud)
在第一个你有一个符合的实例<Counter>.在第二个你有一个符合的类<Counter>.编译器警告是正确的,因为符合的实例<Counter>不响应countFor:,只有类执行.
Objective-C中的类确实像实例一样工作 - 主要的不同之处在于保留计数对它们没有任何作用.但是,您在-availableCounters数组中存储的不是实例(id类型),而是具有类型的类Class.因此,使用上面指定的-availableCounters定义,您需要的是:
Class counterClass = [[MyModel availableCounters] objectAtIndex: self.index];
return ( [counterClass countFor: self] );
Run Code Online (Sandbox Code Playgroud)
但是,如果您使用实例而不是类,则可能在语义上更好.在这种情况下,您可以执行以下操作:
@protocol Counter
- (NSUInteger) countFor: (Model *) model;
@end
@interface CurrentListCounter : NSObject<Counter>
@end
@interface SomeOtherCounter : NSObject<Counter>
@end
Run Code Online (Sandbox Code Playgroud)
然后您的模型类可以实现以下内容:
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 );
}
Run Code Online (Sandbox Code Playgroud)
然后你使用它就像你上面指定的那样:
id<Counter> counter = [[Model availableCounters] objectAtIndex: self.index];
return ( [counter countFor: self] );
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16097 次 |
| 最近记录: |