I have a class which is supposed to be abstract. In one of it's abstract methods the return type may be an instance of class1,class2 or class3, depending on the class that's implementing the method. I'm wondering how should I declare the method in the abstract class. I thought about using dynamic typing, but I want the return type to be restricted to one of the 3 classes, not every type, and in addition I'm not sure I can override it so that in the inheriting class the return type will not match the return type in the abstract class.
I'd be glad if you could help me with this,
Tnx!
Take a look at this:
#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;
}
This is rather condensed syntax, and memory management sucks, but you can see that newItem
is virtual (sending newItem
to myBA
returns a B
) and covariant, which seems to be what you want.
Note that you could also do:
B *myAB = (B*)[origA newItem];
but that returns an A
, and sending foo
to it would tell you that the class does not respond to selector #foo
. If you omitted the (B*)
cast, you would get a warning about this at compile time.
But ISTM that covariance is no big problem, in Objective-C.