тип возврата «виртуального» метода в target-c - PullRequest
2 голосов
/ 27 июля 2011

У меня есть класс, который должен быть абстрактным. В одном из абстрактных методов возвращаемый тип может быть экземпляром class1, class2 или class3, в зависимости от класса, реализующего метод. Мне интересно, как я должен объявить метод в абстрактном классе. Я думал об использовании динамической типизации, но я хочу, чтобы возвращаемый тип был ограничен одним из 3 классов, а не каждым типом, и, кроме того, я не уверен, что могу переопределить его, чтобы в наследующем классе возвращаемый тип не соответствует тип возвращаемого значения в абстрактном классе.

Я был бы рад, если бы вы могли помочь мне с этим,
Tnx!

1 Ответ

3 голосов
/ 27 июля 2011

Взгляните на это:

#import <Foundation/Foundation.h>

@interface A : NSObject { }
- (A*) newItem;
- (void) hello;
@end

@interface B : A { int filler; }
- (B*) newItem;
- (void) hello;
- (void) foo;
@end

@implementation A
- (A*) newItem { NSLog(@"A newItem"); return self; }
- (void) hello { NSLog(@"hello from A"); }
@end

@implementation B
- (B*) newItem { NSLog(@"B newItem"); return self; }
- (void) hello { NSLog(@"hello from B: %d", filler); }
- (void) foo { NSLog(@"foo!"); }
@end

int main (int argc, const char * argv[])
{

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    A *origA = [A new];
    A *myA = [origA newItem];

    NSLog(@"myA: %@", myA);

    B *origB = [B new];
    B *myB = [origB newItem];
    A *myBA = [origB newItem];

    NSLog(@"myB: %@\nmyBA: %@", myB, myBA);

    [origA hello];
    [origB hello];
    [myA hello];
    [myB hello];
    [myBA hello];

    NSLog(@"Covariance?");

    [pool drain];
    return 0;
}

Это довольно сжатый синтаксис, и управление памятью отстой, но вы можете видеть, что newItem является виртуальным (отправка newItem на myBA возвращает B) и ковариантным, что, по-видимому, является тем, что вам нужно.

Обратите внимание, что вы также можете сделать:

    B *myAB = (B*)[origA newItem];

но это возвращает A, и отправка ему foo скажет вам, что класс не отвечает на селектор #foo. Если вы пропустили приведение (B*), вы получите предупреждение об этом во время компиляции.

Но в ISTM эта ковариация не является большой проблемой, в Objective-C.

...