Obj-c方法覆盖/多态问题

时间:2010-06-10 19:50:48

标签: objective-c polymorphism override

好的,我正在使用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];

但我当然不应该这样做以获得我需要的功能吗?否则我将不得不为每个子类添加一个语句,如果我添加一个新的子类,更糟糕的是必须添加一个新的行,这相当于失败方法覆盖的重点不是吗?

当然有更好的方法吗?

2 个答案:

答案 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并且即使aid也不会抱怨。但是,请确保方法名称与其他名称不一致。

(顺便说一句,在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。

您确定编译器知道您调用的方法签名吗?