我有以下课程hierachy:
@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运行时将调用解析到另一个位置:
如果将Message
基类重命名为其他内容,则不会发生错误,例如AbstractMessage
。看来还有另一个名为Message
的类,其定义不公开。
这是一个错误吗?这里到底发生了什么?我是否违反了任何命名限制(即使我认为编译器应该警告我)?
这是XCode 3.1。为iPhone OS 3.0编译。
答案 0 :(得分:8)
Objectve-C缺乏名称空间的概念。这个问题是众所周知的,并且通常使用前缀命名空间(例如 NS Object或 MK MapView)来解决。您可以将消息类命名为JrMessage
,以避免与名为Message
的(未记录的)类发生冲突。
编译器只能在知道其他类时发出警告。对于私有的,未记录的类,通常情况并非如此。处理此问题的最佳方法是通过在每个类上使用前缀来避免冲突。这也有助于防止未来的冲突,当Apple为新版本的操作系统添加类时(编译器显然无法警告)。
修改强>
进一步调查表明,竞争类来自名为“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。
中添加此信息