2010-01-04 77 views
3

我有一个NSObject的子类实现了-(id)initWithRootElement:(MyElement *)e方法。 NSXMLDocument具有一个采用NSXMLElement的相同方法。当我编译,我得到以下警告:无法弄清'警告:不兼容的Objective-C类型'

warning: incompatible Objective-C types 'struct MyElement *', expected 'struct NSXMLElement *' when passing argument 1 of 'initWithRootElement:' from distinct Objective-C type

在这种情况下,我与锵+ LLVM对雪豹进行编译和Xcode 3.2.1,不过这也与GCC 4.2发生在两个豹纹雪豹。

我不明白为什么当NSXMLDocument必须先从NSXMLNode继承时,它为我的直接NSObject子类抛出警告?难道它不知道-(id)initWithRootElement:(NSXMLElement *)e仅适用于与我的课程无关的NSXMLDocument吗?我可以理解,如果我试图超负荷的方法,但我不是。请告诉我我不会发疯......

#import <Foundation/NSAutoreleasePool.h> 
#import <Foundation/NSXMLElement.h> 
// Importing this here causes the warning... 
// #import <Foundation/NSXMLDocument.h> 

typedef NSObject MyElement; 

@interface TestClass : NSObject 
{ 
} 

- (id)initWithRootElement:(MyElement *)element; 
@end 

@implementation TestClass 
- (id)initWithRootElement:(MyElement *)element { return nil; } 
@end 

// ...but here it doesn't 
// #import <Foundation/NSXMLDocument.h> 

int main (int argc, const char * argv[]) 
{ 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    // No warning! Inheritance: NSXMLDocument -> NSXMLNode -> NSObject 
    NSXMLElement *xmlElement = [[NSXMLElement alloc] initWithName:@"foo"]; 
    [[TestClass alloc] initWithRootElement:xmlElement]; 

    // warning: incompatible Objective-C types 'struct MyElement *', expected 'struct NSXMLElement *' when passing argument 1 of 'initWithRootElement:' from distinct Objective-C type 
    MyElement *element = [[MyElement alloc] init]; 
    [[TestClass alloc] initWithRootElement:element]; 

    [pool drain]; 
    return 0; 
} 

回答

11

Objective-C不支持协变声明。

initWithRootElement:在NSXMLDocument声明如下:

- (id)initWithRootElement:(NSXMLElement *)element; 

这是比你的声明不同:

- (id)initWithRootElement:(MyElement *)element; 

在该参数的类型是不同的。这会导致混乱,这行代码(其中elementMyElement *类型的...

[[TestClass alloc] initWithRootElement:element]; 

...因为+alloc返回类型是id,因此,编译器不知道使用哪种方法;哪个参数的类型是可以预期的

当使用Objective-C针对苹果公司的框架代码开发,经验法则是从来没有宣布任何给定的选择不同的参数

我。略感到惊讶的是,第一个案件也没有警告。它可能应该。如果你有一个相当简单的测试用例,请通过http://bugreport.apple.com/提交一个bug,然后在这个问题(或者我的回答)中附加bug#。

+0

谢谢Bill!我完全忘了+ alloc返回的id。现在完美。 我确实打算改变方法名称,但当我无法弄清楚它为什么会警告我时会感到不安。 – 2010-01-04 04:55:52

+0

嗨@bbum,我希望你能对这种情况提供一点说明。 'id'类型有一个类型为Class的'isa'指针,所以说objc不能遍历类层次结构来找到合适的选择器?即使从+ alloc返回'id',这种策略也可以在这种情况下工作,因为这两个类仅在层次结构顶部共享NSObject超类。谢谢! – rpj 2011-05-05 18:29:38

相关问题