I am trying to create an object only instantiatable through a factory method. I prevented init
being used by throwing an exception (see Creating a class with no init method). However this meant that I had to create a new method secretInit to use in the factory method.
//Factory method
- (URLReqs *)buildURLReq:(NSString *)location
{
URLReqs *tmp=[[URLReqs alloc] secretInit];
tmp.str=location
return tmp;
}
- (id) secretInit{
return [super init];
}
This method is messy and while we can avoid declaring secretInit in the header file, someone could still access it. Is there a nicer solution?
One idea is to try开发者_JAVA百科 calling init on the super object of URLReqs directly rather than creating a function to do it.
You don't want to do it this way, but it is possible:
#include <objc/message.h>
@implementation MyClass
+ (id) factoryMethodWithParameter:(NSString *) someString;
{
struct objc_super instanceSuper;
id myInstance = [self alloc];
instanceSuper.receiver = myInstance;
instanceSuper.super_class = [self superclass];
// instanceSuper.class = [self superclass]; // use this line if the above doesn't compile
myInstance = objc_msgSendSuper (&instanceSuper, @selector(init));
//continue on setting up myInstance's ivars . . .
[myInstance setVariable:someString];
return myInstance;
}
- (id) init
{
self = [super init];
if (!self) return nil;
[self release];
[self doesNotRecogniseSelector:_cmd];
return nil;
}
@end
This will allow you to continue to send init
messages to myInstance
's “super” object, but won't allow anyone to send init
to MyClass
instances.
Be careful though, although this is using standard runtime functions declared in objc/*.h
, don't expect Apple to keep this runtime API consistent.
The solution is to use a category on your object to hide the secret initialization method.
Private Methods through categories
What goal are you trying to accomplish? There might be a better solution than this.
It only exposes it if it's referenced in the header file.
No, wait. I should state that another way. There's no better way to hide it than to not declare it in the header file. Private methods don't exist in Objective-C.
精彩评论