2010-05-17 49 views
3

我有下面的类层次结构:目的-C运行时错误当命名超类“消息”

@interface Message : NSObject {} 
@end 

@implementation Message 
- (void) dealloc 
{ 
    // I won't be called 
    [super dealloc]; 
} 
@end 

@interface FooMessage : Message {} 
@end 

@implementation FooMessage 
- (void) dealloc 
{ 
    // should call Message - dealloc 
    [super dealloc]; 
} 
@end 

和以下单元测试:

- (void) test 
{ 
    FooMessage* msg = [[FooMessage alloc] init]; 
    [msg release]; 
} 

测试将总是失败,并EXC_BAD_INSTRUCTION 。 FooMessage称它为dealloc中的超类析构函数,但是电话永远不会到达那里。相反,Objective-C运行解析调用到不同的位置: StackTrace and disassembly

如果Message基类被重命名为别的东西,如不发生错误AbstractMessage。看起来还有另一个类Message,其定义不公开。

这是一个错误?这里发生了什么?我是否违反了任何命名限制(即使我认为编译器应该警告我)?

这是XCode 3.1。编译为iPhone OS 3.0。

回答

8

Objectve-C缺乏名称空间的概念。这个问题是众所周知的,通常通过使用前缀命名空间来解决(比如NS Object或MK MapView)。您可以将您的消息类别命名为JrMessage以避免与名为Message的(未记录的)类发生冲突。

只有当编译器知道其他类时,编译器才会发出警告。对于私人的,无证件的类,通常情况并非如此。处理此问题的最佳方法是通过在每个课程中使用前缀来避免冲突。这也有助于防止未来的冲突,当苹果增加类的新版本的操作系统(编译器显然无法警告)。

编辑:

进一步的调查显示,从名为“MIME.framework”,至少在iPhone模拟器的私人框架竞争的阶级出身:

NSLog(@"Message class: %@", [[NSBundle bundleForClass:NSClassFromString(@"Message")] bundlePath]); 

... Message class: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.3.sdk/System/Library/PrivateFrameworks/MIME.framework 

您可能要添加这个信息在你的bug report

+1

无前缀的类是系统框架中的一个错误。您的控制台上可能会有关于碰撞的消息。通过http:// bug reporter.apple.com/ – bbum 2010-05-17 14:43:25

+0

@bbum提交bug:您是否知道Apple在文档中提供关于类名的承诺? – 2010-05-17 15:48:12

+0

这是...倒退。但是,谢谢你的信息。 – 2010-05-17 16:09:16