对象只能通过工厂方法初始化(Objective-c)

时间:2010-02-03 00:27:53

标签: objective-c

我正在尝试创建一个只能通过工厂方法实例化的对象。我通过抛出异常来阻止使用init(请参阅Creating a class with no init method)。但是这意味着我必须在工厂方法中创建一个新方法secretInit。

//Factory method
- (URLReqs *)buildURLReq:(NSString *)location
{
    URLReqs *tmp=[[URLReqs alloc] secretInit];
    tmp.str=location
    return tmp;
}

- (id) secretInit{
    return [super init];
}

这种方法很麻烦,虽然我们可以避免在头文件中声明secretInit,但仍有人可以访问它。有更好的解决方案吗?

一个想法是尝试直接在URLReqs的超级对象上调用init,而不是创建一个函数来执行它。

3 个答案:

答案 0 :(得分:1)

你不想这样做,但有可能:


#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

这样您就可以继续向init的“超级”对象发送myInstance条消息,但不允许任何人发送initMyClass个实例

但要小心,尽管这是使用objc/*.h中声明的标准运行时函数,但不要指望Apple保持此运行时API的一致性。

答案 1 :(得分:0)

解决方案是使用对象上的类别来隐藏秘密初始化方法。

Private Methods through categories

你想要达到什么目标?可能有比这更好的解决方案。

答案 2 :(得分:0)

只有在头文件中引用它时才会公开它。

不,等等。我应该说另一种方式。没有更好的隐藏方法,而不是在头文件中声明它。 Objective-C中不存在私有方法。