Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid subclass inadvertently overriding superclass private method

I'm writing a library, which will potentially be used by people that aren't me.

Let's say I write a class:

InterestingClass.h

@interface InterestingClass: NSObject
- (id)initWithIdentifier:(NSString *)Identifier;
@end

InterestingClass.m

@interface InterestingClass()
- (void)interestingMethod;
@end

@implementation InterestingClass
- (id)initWithIdentifier:(NSString *)Identifier {
  self = [super init];
  if (self) {
    [self interestingMethod];
  }
  return self;
}

- (void)interestingMethod {
  //do some interesting stuff
}
@end

What if somebody is using the library later down the line and decides to create a subclass of InterestingClass?:

InterestingSubClass.h

@interface InterestingSubClass: InterestingClass
@end

InterestingSubClass.m

@interface InterestingSubClass()
- (void)interestingMethod;
@end

@implementation InterestingSubClass
- (void)interestingMethod {
  //do some equally interesting, but completely unrelated stuff
}
@end

The future library user can see from the public interface that initWithIdentifier is a method of the superclass. If they override this method, they'll probably assume (correctly) that the superclass method should be called in the subclass implementation.

However, what if they define a method (in the subclass private interface) which inadvertently has the same name as an unrelated method in the superclass 'private' interface? Without them reading the superclass private interface, they won't know that instead of just creating a new method, they've also overridden something in the superclass. The subclass implementation may end up getting called unexpectedly, and the work that the superclass is expecting to be done when calling the method will not get done.

All of the SO questions I've read seem to suggest that this is just the way that ObjC works and that there isn't a way of getting around it. Is this the case, or can I do something to protect my 'private' methods from being overridden?

Alternatively, is there any way to scope the calling of methods from my superclass so I can be sure that the superclass implementation will be called instead of a subclass implementation?

like image 210
sam-w Avatar asked Jan 31 '13 14:01

sam-w


2 Answers

AFAIK, the best you can hope for is declaring that overrides must call super. You can do that by defining the method in the superclass as:

- (void)interestingMethod NS_REQUIRES_SUPER;

This will compile-time flag any overrides that don't call super.

like image 134
Clay Bridges Avatar answered Oct 20 '22 08:10

Clay Bridges


For framework code a simple way to deal with this is to just give all of your private methods a private prefix.

You'll often notice in stack traces that the Apple frameworks call private methods often starting with an under bar _.

This would only really be a real concern if you are indeed providing a framework for external use where people can not see your source.

NB
Don't start your methods with an under bar prefix as this convention is already reserved

like image 42
Paul.s Avatar answered Oct 20 '22 09:10

Paul.s