Reputation: 551
I have a base class that has class methods defined for returning various pieces of information that I use to build service url's. The base class also has an instance method defined for building that URL. I would like the base class to have a default implementation of this method, so that I only have to override it in my subclasses when I need the url to be different. How do I have this base method call the overridden class methods to build the url using the class methods from the subclass? Below is the code I have now that is not working:
The base class method:
- (NSString *)buildRequestUrlString{
return [Utils serviceEndpointForOperationId:[[self class]operationId] version:[[self class] operationVersion] andRequestMethod:[[self class] methodType];
}
operationId, operationVersion and methodType are the class methods that are implemented in the subclass, but when the subclass makes the following call:
[super buildRequestUrlString];
It is using the class methods from the base class to build my endpoint, and not the class methods in my subclass. How do I make it not do that? Is it even possible?
Thanks in advance,
Nick
Upvotes: 0
Views: 2115
Reputation: 162722
Use self
instead of super
.
[self buildRequestUrlString];
(Or explain why that doesn't work in your case).
Responding to the comment, it sounds like your class decomposition is incorrect (or you are confused). Specifically, this is likely why you've received three answers that were all "use self
"; we don't understand where the problem is.
If your base class needs to call an instance method from a subclass, then it needs a reference to an instance of the subclass. I.e. say you have:
@interface Concrete:Base
Then, Base might implement a class method like:
+ baseWithConcreteQuantity:(int)aQuant
{
return [[self alloc] initWithConcreteQuantity:aQuant];
}
And it would be used like:
[Concrete baseWithConcreteQuantity:10];
That is, class methods in Objective-C -- unlike static methods in other languages -- are inherited just like instance methods.
Now, as for the instance method, you always call super
's implementation of a particular method from that method. Using super
to call a different method of the base class is pretty much never done and is a sure sign that something else is wrong.
Similarly, the base class should never try to specifically call functionality in a subclass that doesn't exist in the base.
I.e.
// in base
...
[self doSomething];
...
- (void)doSomething { ; }
// where a subclass might
- (void)doSomething { ... ; [super doSomething]; }
Upvotes: 1
Reputation: 2577
In your "buildRequestUrlString"-method your [self class] is obviously of type "base class".
Object Inheritance Guidelines would strongly disagree with trying to access properties of subclasses from your father-class, since the father-class has (and should have) no knowledge whether subclasses even exist.
Guess, I don't type fast enough, to solve this do what bbum said ;)
EDIT: This'd be a hack, and against what I just said, but you could hand over the class-name as an argument:
- (NSString *)buildRequestUrlString:(Class)theClass{
if (!theClass) theClass = [self class];
return [Utils serviceEndpointForOperationId:[theClass operationId] version:[theClass operationVersion] andRequestMethod:[theClass methodType]];
}
[super buildRequestUrlString:[self class]];
Upvotes: 0
Reputation: 2083
I would use the template pattern for this. Basically create 3 instance methods in your base class to get your operationId, etc. in the base class they just return nil. Then in your subclasses override these 3 methods to return the correct values.
Your buildRequestUrlString method uses the [self operationId] etc.
Upvotes: 0