Skip to content

Instantly share code, notes, and snippets.

@BenedictC
Created March 7, 2012 19:51
Show Gist options
  • Save BenedictC/1995580 to your computer and use it in GitHub Desktop.
Save BenedictC/1995580 to your computer and use it in GitHub Desktop.
Faking Protected Methods in Objective-C
//
// main.m
// Protected
//
// Created by Benedict Cohen on 07/03/2012.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
//
// Unlike other object orientated languages Objective-C does not
// provide a mechanism for scoping methods as public, protected or private.
// In Objective-C all methods are essentially public. Private methods can be
// faked by declaring the methods within an anonymous @interface within the
// implementation file (i.e. the .m file).
//
// That only leaves protected methods. The common practice is to simply make
// a note in the documentation or in a comment that a method should be treated
// as protected. This approach isn't ideal because:
// - Not everyone reads the comments/documentation
// - Code can change and the comments/documentation not updated
//
// The following is a macro that allows protected methods to be annotated in
// the code. It's incredibly simple. It works by appending a string to the end
// of the method name. It also works with properties too. The intend is not to
// enforce method scope but to indicate the indent of a method.
/*************************************
The macro
This is the macro that does the magic. It's stupidly simple
The string is append not prepended so that setters remain sane
*************************************/
#ifndef PROTECTED
#define PROTECTED(methodName) methodName ## _protected
#endif
/*************************************
BaseClass
This is the base class that has some protected methods
*************************************/
#import <Foundation/Foundation.h>
@interface BaseClass : NSObject
//a protected method. Note that the colon is outside of the macro.
-(void)PROTECTED(aProtectedMethod):(id)withAnArgument;
//a protected property.
@property(readwrite, nonatomic, strong) NSString * PROTECTED(aName);
@end
@implementation BaseClass
//implmenting a protected method
-(void)PROTECTED(aProtectedMethod):(id)withAnArgument
{
NSLog(@"%@ - %@", [self className], NSStringFromSelector(_cmd));
}
//implementing a protected property. Note that we are still specifing the name of the ivar to use to the property.
@synthesize PROTECTED(aName) = _aName;
@end
/*************************************
SubClass
This is the subclass which will access the protected methods
*************************************/
@interface SubClass : BaseClass
//Nothing special about these declarations
-(void)callSuperProtected;
//this is simple exposing supers protected method
@property(readonly) NSString *aName;
@end
@implementation SubClass
-(void)callSuperProtected
{
//Calling a protected method on super. Again, note that the colon is outside of the macro.
[super PROTECTED(aProtectedMethod):nil];
}
-(NSString *)aName
{
//It works with dot syntax too! (OK, this does look weird).
return super.PROTECTED(aName);
}
@end
/*************************************
Other calling examples
*************************************/
int main(int argc, const char * argv[])
{
@autoreleasepool {
//This line will not compile due to a 'method not found' error
//[[BaseClass new] aProtectedMethod:nil];
//Code-completion will still suggest the protected methods but they will be
//displayed as 'aProtectedMethod_protected:' so it's clear what there purpose is.
//This line will compile
[[BaseClass new] aProtectedMethod_protected:nil];
//This line will compile
[[SubClass new] callSuperProtected];
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment