2011-12-13 34 views
3

我已經創建了一個名爲Foo類:呼籲變量的子方法類型爲超

@interface Foo:NSObject{ 
    int myInt; 
} 
@property int myInt; 
@end 

,並命名爲BarFoo一個子類:

@interface Bar:Foo{ 
    NSString *myString; 
} 
@property (copy) NSString *myString; 
@end 

我試圖存儲Bar爲一個Foo陣列中的對象,如下所示:

-(void)createBar{ 
    Foo *object = [[Bar alloc]init]; 

    // myArray is an instance of NSMutableArray 
    [myArray addObject:object]; 
} 

我這樣做是因爲我實際上有Foo的多個子類(我不想全部列出)。當我從數組中獲取對象並將消息發送給對象以獲取myString變量時,應用程序不會執行任何操作。 例子:

-(NSString *)getStringFromFooAtIndex(NSUInteger)index{ 
    Foo *object = [myArray objectAtIndex:index]; 

    return [object myString]; 
} 

我誤解 '消息' 是如何工作的?我的假設是我可以發送消息給一個對象,它會調用它是否存在或不存在。我需要以其他方式做這個嗎?該數組將包含所有不同類型的Foo子類,我需要它將它們存儲在那裏。

+1

你在@synthesize你的屬性? – dasblinkenlight 2011-12-13 17:11:27

+0

是的,我在執行文件中。 – 2011-12-13 17:19:19

回答

3

我的假設是我可以發送消息給一個對象,它會調用它是否存在或不存在。

確實可以發送任何消息給任何對象;這是Objective-C樂趣的一部分。 變量的類型Foo *,Bar *,id或其他任何內容)具有對消息發送沒有影響。變量指向的對象知道它的類。相應方法的查找是在運行時通過該類來完成的。編譯器將括號內的表達式轉換爲對函數objc_msgSend的調用。

你應該建立時,說:「‘富’可能不是‘myString的’迴應」來獲取有關[object myString]警告 - 編譯器知道有具有對應於myString的方法至少一類的地方,它知道在編譯時,Foo似乎不是其中之一,但它不能保證Foo在運行時將無法對消息執行某些操作。消息可以解決in custom ways during runtime。請注意,如果將變量的類型更改爲id,則警告消失 - 編譯器不能再推斷可用的方法。

如果事實證明,您發送的對象myString不對作出響應。,如果對象確實是 a Foo而不是BarFoo的子類中的一個沒有實現myString),則會引發異常。這是默認響應(由從NSObject繼承的任何內容)到無法識別的消息。

如果您有需要發送消息的異構對象集合,則可能需要先測試每個對象。你可以做jstevenco建議,並測試功能:

if([object respondsToSelector:@selector(myString)]){ 

或測試身份:

if([object isKindOfClass:[Bar class]]){ 

如果對象是一個Bar或任何Bar的子類,後者會通過。使用isMemberOfClass:僅對您指定的類進行測試。

1

請參閱here瞭解如何處理消息傳遞邏輯。如果你不覆蓋-(void)doesNotRecognizeSelector:(SEL)aSelector,最終會產生一個錯誤。

如果你打算做一個多態的對象集合,你應該首先用respondsToSelector:來測試這個對象,然後根據你的需要直接調用該方法或者使用其中一個performSelector:變體。另一種可能性是將myString的實現包含在不執行任何操作的基類中。

0

我想出了問題所在。

以我AppDelegate.m文件我有以下方法:

- (void)createFoo{ 
    Foo *foo = [[Bar alloc]init]; 

    [myArrayController add:foo]; 
} 

這被插入「富」對象到我的陣列控制器。我也有這種定義方法:

- (void) insertObject:(Foo *)object intoMyArrayControllerAtIndex:(NSUInteger)index{ 
    // handles the inserting of the object as well as working with the undo manager 
} 

現在,調用[myArrayController add:foo]是什麼導致了問題。如果我用[self insertObect:foo intoMyArrayControllerAtIndex:0]替換那條線,那麼一切都很完美。

非常感謝你和遺憾浪費你的時間。