开发者

Object only initialisable through factory method (Objective-c)

开发者 https://www.devze.com 2022-12-19 03:48 出处:网络
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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消