编辑:问题解决了!清洁并重新启动后它就消失了!我不知道是什么造成的!
这让我头疼了整整一天:
在Xcode 3.2中,一切都很出色。然后我切换到4.2,突然一个类继承不再起作用了。
我有一个班级TheSuperclass
和TheSubclass : TheSuperclass
。为了简化测试,我真的像这样创建它们。没有比你在这里看到的更多的代码:
// TheSuperclass.h
@interface TheSuperclass : NSObject {
}
// subclasses must override this method
- (id)returnSomethingUseful;
@end
// TheSuperclass.m
#import "TheSuperclass.h"
@implementation TheSuperclass
- (id)returnSomethingUseful {
NSLog(@"Dude, you have to override -returnSomethingUseful");
return nil; // subclasses override this method!
}
- (id)init {
if ((self = [super init])) {
obj = [self returnSomethingUseful]; // TEST
NSLog(@"TheSuperclass initialized: %@", obj);
}
return self;
}
@end
// TheSubclass.h
#import "TheSuperclass.h"
@interface TheSubclass : TheSuperclass {
}
@end
// TheSubclass.h
#import "TheSubclass.h"
- (id)returnSomethingUseful {
NSLog(@"Correct method called!");
return usefulObject;
}
TheSubclass *foo = [[TheSubclass alloc] init]; // remember: init of superclass calls the method
// Getting the NSLog: "Dude, you have to override -returnSomethingUseful"
id bar = [foo returnSomethingUseful]; // now call it directly on foo
// Getting the NSLog: "Correct method called!"
TheSuperclass
声明了一个模板方法,即一个什么都不做的方法,返回nil并用于子类化:
- (id)returnSomethingUseful {
NSLog(@"Dude, you have to override -returnSomethingUseful");
return nil; // subclasses override this method!
}
在TheSubclass
中,我只是覆盖了该模板方法。当然,我将TheSuperclass
中的实现归结为100%正确。没有错字。这是一个经过检查的事实。看起来像这样:
- (id)returnSomethingUseful {
NSLog(@"Correct method called!");
return usefulObject;
}
在TheSuperclass
的实现中,一段代码调用[self returnSomethingUseful]
以便从模板方法中获取该对象。这是一个伟大的模式,我已经使用了很多。它总是像这样工作。
但是现在看来即使我创建了TheSubclass
的实例,它总是调用WRONG方法。 TheSuperclass中的那个,而不是它应该的那个(当然这是最重要的方法)
我已经检查了至少100次!说真的,它是TheSubclass
的一个实例。它调用TheSuperclass
的init方法给我NSLogs。
现在真正奇怪的部分:当我从“外部”在我的TheSubclass对象上调用该方法时,它可以工作:
TheSubclass *foo = [[TheSubclass alloc] init];
id bar = [foo returnSomethingUseful];
// Getting the NSLog: "Correct method called!"
所以要强调它:当我从TheSuperclass的实现中调用[self returnSomethingUseful]
时,它调用WRONG实现(它是超类之一,而不是子类中被覆盖的实现。
那我怎么解决这个问题呢?这可能来自哪里?这是运行时中的问题,可能是由编译器中的错误引起的吗?
答案 0 :(得分:4)
LLVM显然能够正确实现简单的子类化。成千上万的程序每天都在使用它,所以如果你正在编写标准代码(不要尝试任何棘手或无证的代码),这不是一个需要解决的问题。以下是你应该做的事情:
[self class]
以确保您的确如此。isa
指针(很容易找到;在您的代码中搜索->isa
)。init
。这是做一些过于棘手的事情的最有可能的地方。确保你遵循简单的模式。答案 1 :(得分:2)
如果编译器搞砸了一些基本的东西,系统将无法启动。
在init
方法中断言该类,因为您有一个TheSuperclass实例或者拼写错误。
答案 2 :(得分:1)
术语是“覆盖”,而不是“覆盖”。
您还没有向我们展示足够的代码来了解问题所在。向我们展示两个类的-init方法,并向我们展示创建子类实例的位置。