2009-05-31 71 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

相關問題