Проблема переопределения / полиморфизма метода Obj-c - PullRequest
0 голосов
/ 10 июня 2010

Хорошо, поэтому я использую 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 (предположительно, потому что компилятор не может определить фактическийтип объекта до времени выполнения).Но, если серьезно, я также получаю сообщение об ошибке «void value не игнорируется, как должно быть», и он не будет компилироваться.

Если я не попытаюсь использовать возврат из [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 ]

1 голос
/ 10 июня 2010

Поскольку 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 геттеры не будут называться -getFoo. Соглашение просто называть его -foo.)

0 голосов
/ 11 июня 2010

Ваш код компилируется без предупреждения:

#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» всегда выполняется, поскольку MidClass и BotClass наследуются от TopClass.знает о сигнатурах методов, которые вы вызываете?

...