iosobjective-cnsobject

how to forbid the basic init method in a NSObject


I want to force user to use my own init method (for example -(id)initWithString:(NSString*)foo;) and not the basic [[myObject alloc]init];.

how can I do that?


Solution

  • The accepted answer is incorrect - you CAN do this, and it's very easy, you just have to be a bit explicit. Here's an example:

    You have a class named "DontAllowInit" which you want to prevent people init'ing:

    @implementation DontAllowInit
    
    - (id)init
    {
        if( [self class] == [DontAllowInit class])
        {
            NSAssert(false, @"You cannot init this class directly. Instead, use a subclass e.g. AcceptableSubclass");
    
            self = nil; // as per @uranusjr's answer, should assign to self before returning
        }
        else
            self = [super init];
    
        return nil;
    }
    

    Explanation:

    1. When you call [super init], the class that was alloc'd was the SUBCLASS.
    2. "self" is the instance - i.e. the thing that was init'd
    3. "[self class]" is the class that was instantiated - which will be SUBCLASS when the SUBCLASS is calling [super init], or will be the SUPERCLASS when the SUPERCLASS is being called with plain [[SuperClass alloc] init]
    4. So, when the superclass receives an "init" call, it just needs to check whether the alloc'd class is the same as its own class

    Works perfectly. NB: I don't recommend this technique for "normal apps" because usually you INSTEAD want to use a Protocol.

    HOWEVER ... when writing Libraries ... this technique is VERY valuable: you frequently want to "save (other developers) from themselves", and its easy to NSAssert and tell them "Oops! you tried to alloc/init the wrong class! Try class X instead...".