2011-12-13 35 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]替换那条线,那么一切都很完美。

非常感谢你和遗憾浪费你的时间。