views:

255

answers:

2

I have class X, an abstract class, and classes A and B that inherit from it. Classes A and B each have their own 'return_something' function. I have another method elsewhere that calls 'return_something' on a series of objects, all of type X. 'return_something' returns something different depending on whether it is an A or a B, so I can just call id *result = [x return_something).

I can design this all fine, but when I come to implementing it I don't know what to put in class X, the parent. It needs to have a 'return_something' function in order for it to be callable, but the function itself is defined in the child classes. I can declare it in the parent and both children, but I don't have anything to return from the X implementation - the returned object is dependent on the child's re-definition.

This would be fine for a non-returning method, but how am I meant to use inheritance and polymorphism with a function?

+5  A: 

The simplest thing to do is throw an exception from the "base" function. That way you'll know if it gets called by mistake.

Other languages which provide explicit "abstractness" don't require method bodies for abstract methods.

Anon.
Exactly - the best implementation I've seen is in Eiffel, where you explicitly state that the class is abstract and the routine is deferred.So you're saying just to return something (because I have to) and it might as well be an exception so that I know about it, right? But what if I'm doing some generic things in the base definition, and calling [super return_something] in the child? The base class will return the exception and bail from the child code immediately?
Ben Packard
If you're expecting the child routines to actually call the base routine, then it's not really "abstract". If it's an abstract routine, then the base-class implementation should not be called.
Anon.
It's abstract in the sense that it shouldn't be created, but it has some generic qualities that all children share. Maybe I need to re-visit my definitions. Eg I might never want to create a 'vehicle', only a car or a bus, but each has a 'drive' routine with a lot of similar code that could be in the base class. I guess as a work around, I could have the generic code in a new method in the base class, that each child calls as part of their own implementation. Seems a bit inelegant though.
Ben Packard
As far as the abstract class goes, some of the methods will have "default" implementations in the base class, but others (the "abstract" methods) will not. Those "abstract" implementations should not be called, ever.
Anon.
ok so I can just declare function in the interface file (of the base class), and put nothing in the implementation file? And then define it again in each child, and also implement it.I'm guessing I'll get a warning from the compiler?
Ben Packard
You need something in the base class. That's where you throw an exception that says something like "Must be implemented by subclass."
Jon Reid
If the compiler lets you declare it with no implementation, then that would be the best. If it doesn't, then you should implement it to just throw an exception.
Anon.
+5  A: 

Use an objective-C protocol instead of an abstract base class:

@protocol ProtocolX
-(int)return_something;
@end

@interface ClassA : NSObject <ProtocolX> {
}
-init;
-(int)return_something;
@end

@interface ClassB : NSObject <ProtocolX> {
}
-init;
-(int)return_something;
@end

@implementation ClassA : NSObject <ProtocolX>
-(int)return_something { return 1; }
-init { retur [super init]; }
@end

@implementation ClassB : NSObject <ProtocolX>
-(int)return_something { return 3; }
-init { retur [super init]; }
@end

References of type id<ProtocolX> can then be passed around and used:

id<ProtocolX> ref = [[ClassA alloc] init];
int myIntForA = [ref return_something];
[ref release];
ref = [[ClassB alloc] init];
int myIntForB = [ref return_something];
[ref release];
martinr
Interesting, thanks - I'll bust out my book and get reading, not come across protocols yet. That looks deceptively simple!
Ben Packard
Works if the base class is completely "abstract", e.g. there's no state or default methods.
quixoto
Yep I see - I would like to have some generic code in the base class definition so not sure this will work. Might re-design in order to use it though.
Ben Packard
Am I correct in thinking a protocol CAN NOT have any variables or implementation code of it's own? If so it's not a viable solution for me.
Ben Packard
You can declare a non-abstract base class, common to A and B, AS WELL as use a protocol to emulate abstract methods for bits you don't want in a base class.
martinr
Very smart - thanks
Ben Packard