2009-05-31 138 views
10

我有一系列“策略”对象,我认为这些对象可以方便地在一组策略类中作为类方法实现。我已指定的协议对于这一点,和创建的类,以符合(只有一个如下所示)如何在不引用类的情况下调用Objective C中的+类方法?

@protocol Counter 
+(NSInteger) countFor: (Model *)model; 
@end 

@interface CurrentListCounter : NSObject <Counter> 
+(NSInteger) countFor: (Model *)model; 
@end 

我然后必须符合此协议(像CurrentListCounter一样)的类的数组

+(NSArray *) availableCounters { 
return [[[NSArray alloc] initWithObjects: [CurrentListCounter class], [AllListsCounter class], nil] autorelease]; 
} 

注意我如何使用对象类(这可能是我的问题 - 在Smalltalk类是像对象一样的对象 - 我不知道它们是否在Objective-C?)

我的确切的问题是当我想打电话给我的时候, licy对象从数组中:

id<Counter> counter = [[MyModel availableCounters] objectAtIndex: self.index]; 
return [counter countFor: self]; 

我得到return语句的警告 - 它说-countFor:在协议未找到(因此它假定它,我想调用类方法的实例方法)。然而,由于我的数组中的对象是类的实例,它们现在像实例方法(或概念上它们应该是)。

是否有一种神奇的方法来调用类方法?或者这只是一个坏主意,我应该创建我的策略对象的实例(而不是使用类方法)?

+0

计数器不计数器 – 2009-05-31 12:31:10

回答

19

id <Counter> counter = [[Model availableCounters] objectAtIndex:0]; 
return ([counter countFor: nil]); 

Class <Counter> counter = [[Model availableCounters] objectAtIndex:0]; 
return ([counter countFor: nil]); 

在第一你必须符合<Counter>一个实例。第二,你有一个符合<Counter>的课程。编译器警告是正确的,因为符合<Counter>的实例不响应countFor:,只有类符合要求。

0

事实证明,它实际上工作,并且警告是不正确的。

所以问题仍然是它是否合理的事情(如果他们不需要任何状态使用类方法)?

以及如何最好地处理警告(我喜欢免费运行警告)?

我唯一的解决办法是有一个第二协议(本质上是相同的第一,但宣告它的实例侧):

@protocol CounterInstance 
-(NSInteger) countFor: (Model *)model; 
@end 

而且在那里我访问计数器用它来代替(欺骗编译器):

id<CounterInstance> counter = [[MyModel availableCounters] objectAtIndex: self.index]; 
return [counter countFor: self]; 

它有点尴尬,但确实有效。我对其他人的看法感兴趣吗?

+0

该警告不正确。 Objective-C的动态特性意味着消息无论如何都被发送到对象。编译器提出警告,让你知道它确实期待实例方法。至于你的解决方案 - 我觉得这很难看。只要做吉姆说的话。 – Abizern 2009-05-31 13:21:02

5

Objective-C中的类确实像实例一样工作 - 主要的根本区别是保留计数对它们没有任何影响。但是,存储在-availableCounters数组中的内容不是实例(类型为id),而是类型为Class的类。因此,与-availableCounters定义上面指定,你需要的是这样的:

Class counterClass = [[MyModel availableCounters] objectAtIndex: self.index]; 
return ([counterClass countFor: self]); 

但是,它很可能是语义上更好,如果你使用的情况下,而不是类。在这种情况下,你可以这样做以下:你上面指定

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); 
} 

那么你的该用途,将是完全相同:

@protocol Counter 
- (NSUInteger) countFor: (Model *) model; 
@end 

@interface CurrentListCounter : NSObject<Counter> 
@end 

@interface SomeOtherCounter : NSObject<Counter> 
@end 

那么你的模型类可以实现以下

id<Counter> counter = [[Model availableCounters] objectAtIndex: self.index]; 
return ([counter countFor: self]); 
+0

谢谢Jim - 我有兴趣看看你能推多少Objective-C。这听起来像是当你碰到类时,它开始时的行为有点不同(尽管它确实有效 - 类仍然是对象,这很好) - 所以也许它更好地坚持实例。 在评论开始的一件事情 - “类counterClass”是避免协议,而我的类也符合“计数器”。我猜想缺少的是能够正确地指定类的协议(在类一侧) - 类似于: @interface CurrentListCounter:NSObject <+Counter> – TimM 2009-06-01 06:34:33

+1

您可能可以使用类counter counterClass。我不确定。但是这样做只能真的限制编译器不会警告的消息 - ObjC类型检查实际上只是顾问。协议可以指定类的方法,所以你不需要任何种类的<+Counter>特殊语法(例如查看NSObject协议)。 – 2009-06-01 15:16:11

相关问题