好的,我正在使用Objective-C。现在,说我有:
TopClass : NSObject
- (int) getVal {return 1;}
MidClass : TopClass
- (int) getVal {return 2;}
BotClass : MidClass
- (int) getVal {return 3;}
然后我将每种类型的对象放入NSMutableArray并取出一个。我想要做的是在适当的对象类型上运行getVal函数,但是当我放入
时id a = [allObjects objectAtIndex:0];
if ([a isKindOfClass:[TopClass class]])
{
int i;
i = [a getVal];
}
我首先得到一个关于getVal的多个方法的警告(可能是因为编译器在运行之前无法确定实际的对象类型)。但更严重的是,我也得到一个错误“无法忽略的空值,因为它应该是”并且它不会编译。
如果我不尝试使用[a getVal]的返回值,那么它会编译得很好。
[a getval]; //obviously no good if I want to use the return value
如果我在运行函数之前使用isMemberOfClass语句将对象强制转换为类,它也会起作用。
if ([a isMemberOfClass:[BotClass]) i = [(BotClass*) a getVal];
但我当然不应该这样做以获得我需要的功能吗?否则我将不得不为每个子类添加一个语句,如果我添加一个新的子类,更糟糕的是必须添加一个新的行,这相当于失败方法覆盖的重点不是吗?
当然有更好的方法吗?
答案 0 :(得分:1)
由于BotClass是MidClass而MidClass是TopClass,因此您只需将a
的类型设置为TopClass*
。
TopClass* a = [allObjects objectAtIndex:0];
if ([a isKindOfClass:[TopClass class]]) {
int i;
i = [a getVal];
}
更好的方法是将-getVal
添加到@interface
和#import
。然后编译器会知道这样的方法可能会返回int
并且即使a
是id
也不会抱怨。但是,请确保方法名称与其他名称不一致。
(顺便说一句,在ObjC中,getter不会被命名为-getFoo
。惯例只是称之为-foo
。)
答案 1 :(得分:0)
您的代码在没有任何警告的情况下编译:
#import <Foundation/Foundation.h>
@interface TopClass : NSObject
{
}
- (int) getVal;
@end
@interface MidClass : TopClass
{
}
- (int) getVal;
@end
@interface BotClass : MidClass
{
}
- (int) getVal;
@end
@implementation TopClass
- (int) getVal {
return 1;
}
@end
@implementation MidClass
- (int) getVal
{
return 2;
}
@end
@implementation BotClass
- (int) getVal
{
return 3;
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSMutableArray *array = [NSMutableArray array];
[array addObject:[[[TopClass alloc]init]autorelease]];
[array addObject:[[[MidClass alloc]init]autorelease]];
[array addObject:[[[BotClass alloc]init]autorelease]];
for (int objectNumber = 0; objectNumber < [array count]; objectNumber++) {
id a = [array objectAtIndex:objectNumber];
if ([a isKindOfClass:[TopClass class]])
{
int i = [a getVal];
NSLog(@"%d",i);
}
}
[pool drain];
return 0;
}
在这种情况下,测试“isKindOfClass”始终为true,因为MidClass和BotClass继承自TopClass。
您确定编译器知道您调用的方法签名吗?