Protected methods in Objective-C
Objective CObjective C Problem Overview
What is the equivalent to protected methods in Objective-C? I want to define methods which only the derived classes may call/implement.
Objective C Solutions
Solution 1 - Objective C
You can simulate protected and private access to methods by doing the following:
- Declare your private methods in a class extension (i.e. a unnamed category declared near the top of the class' .m file)
- Declare your protected methods in a Subclass header – Apple uses this pattern with respect to UIGestureRecognizer (see documentation and reference to UIGestureRecognizerSubclass.h)
These protections are not, as Sachin noted, enforced at runtime (as they are in Java, for example).
Solution 2 - Objective C
> You can neither declare a method protected or private. Objective-C's dynamic nature makes it impossible to implement access controls for methods. (You could do it by heavily modifying the compiler or runtime, at a severe speed penalty, but for obvious reasons this is not done.)
Taken from Source.
Solution 3 - Objective C
Here is what I did to get protected methods visible to my subclasses, without requiring them to implement the methods themselves. This meant I didn't get compiler warnings in my subclass about having an incomplete implementation.
SuperClassProtectedMethods.h (protocol file):
@protocol SuperClassProtectedMethods <NSObject>
- (void) protectMethod:(NSObject *)foo;
@end
@interface SuperClass (ProtectedMethods) < SuperClassProtectedMethods >
@end
SuperClass.m: (compiler will now force you to add protected methods)
#import "SuperClassProtectedMethods.h"
@implementation SuperClass
- (void) protectedMethod:(NSObject *)foo {}
@end
SubClass.m:
#import "SuperClassProtectedMethods.h"
// Subclass can now call the protected methods, but no external classes importing .h files will be able to see the protected methods.
Solution 4 - Objective C
I just discovered this and it works for me.To improve upon Adam's answer, in your superclass make an implementation of the protected method in .m file but don't declare it in .h file. In your subclass make a new category in your .m file with the declaration of the protected method of the superclass and you can use the protected method of the superclass in your subclass. This will not ultimately prevent the caller of the supposedly protected method if forced at runtime.
/////// SuperClass.h
@interface SuperClass
@end
/////// SuperClass.m
@implementation SuperClass
- (void) protectedMethod
{}
@end
/////// SubClass.h
@interface SubClass : SuperClass
@end
/////// SubClass.m
@interface SubClass (Protected)
- (void) protectedMethod ;
@end
@implementation SubClass
- (void) callerOfProtectedMethod
{
[self protectedMethod] ; // this will not generate warning
}
@end
Solution 5 - Objective C
Another way using @protected variables.
@interface SuperClass:NSObject{
@protected
SEL protectedMehodSelector;
}
- (void) hackIt;
@end
@implementation SuperClass
-(id)init{
self = [super init];
if(self) {
protectedMethodSelector = @selector(baseHandling);
}
return self;
}
- (void) baseHandling {
// execute your code here
}
-(void) hackIt {
[self performSelector: protectedMethodSelector];
}
@end
@interface SubClass:SuperClass
@end
@implementation SubClass
-(id)init{
self = [super init];
if(self) {
protectedMethodSelector = @selector(customHandling);
}
return self;
}
- (void) customHandling {
// execute your custom code here
}
@end
Solution 6 - Objective C
You can define the method as a private method of the parent class and can use [super performSelector:@selector(privateMethod)];
in the child class.
Solution 7 - Objective C
One option is to use class extension to hide methods.
In .h
:
@interface SomeAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
In .m
:
@interface SomeAppDelegate()
- (void)localMethod;
@end
@implementation SomeAppDelegate
- (void)localMethod
{
}
@end
Solution 8 - Objective C
You can sort of do this with a category.
@interface SomeClass (Protected)
-(void)doMadProtectedThings;
@end
@implementation SomeClass (Protected)
- (void)doMadProtectedThings{
NSLog(@"As long as the .h isn't imported into a class of completely different family, these methods will never be seen. You have to import this header into the subclasses of the super instance though.");
}
@end
The methods aren't hidden if you import the category in another class, but you just don't. Due to the dynamic nature of Objective-C it's actually impossible to completely hide a method regardless of a calling instance type.
The best way to go is probably the class continuation category as answered by @Brian Westphal but you'll have to redefine the method in this category for each subclassed instance.
Solution 9 - Objective C
I usually name protected method with internal prefix:
-(void) internalMethod;