tags:

views:

1118

answers:

4

I need to hide (make private) the -init method of my class in Objective-C.

How can I do that?

+1  A: 

That depends on what you mean by "make private". In Objective-C, calling a method on an object might better be described as sending a message to that object. There's nothing in the language that prohibits a client from calling any given method on an object; the best you can do is not declare the method in the header file. If a client nevertheless calls the "private" method with the right signature, it will still execute at runtime.

That said, the most common way to create a private method in Objective-C is to create a Category in the implementation file, and declare all of the "hidden" methods in there. Remember that this won't truly prevent calls to init from running, but the compiler will spit out warnings if anyone tries to do this.

MyClass.m

@interface MyClass (PrivateMethods)
- (NSString*) init;
@end

@implementation MyClass

- (NSString*) init
{
    // code...
}

@end

There's a decent thread on MacRumors.com about this topic.

Matt Dillard
Unfortunately, in this case, the category approach won't really help. Normally it buys you compile-time warnings that the method may not be defined on the class. However, since MyClass must inherit from one of the root clases and they define init, there will be no warning.
Barry Wark
Barry, you make an excellent point.
Matt Dillard
A: 

If you are talking about the default -init method then you can't. It's inherited from NSObject and every class will respond to it with no warnings.

You could create a new method, say -initMyClass, and put it in a private category like Matt suggests. Then define the default -init method to either raise an exception if it's called or (better) call your private -initMyClass with some default values.

One of the main reasons people seem to want to hide init is for singleton objects. If that's the case then you don't need to hide -init, just return the singleton object instead (or create it if it doesn't exist yet).

Nathan Kinsinger
+10  A: 

Objective-C, like Smalltalk, has no concept of "private" versus "public" methods. Any message can be sent to any object at any time.

What you can do is throw an NSInternalInconsistencyException if your -init method is invoked:

- (id)init {
    [self release];
    @throw [NSException exceptionWithName:NSInternalInconsistencyException
                                   reason:@"-init is not a valid initializer for the class Foo"
                                 userInfo:nil];
    return nil;
}

The other alternative — which is probably far better in practice — is to make -init do something sensible for your class if at all possible.

If you're trying to do this because you're trying to "ensure" a singleton object is used, don't bother. Specifically, don't bother with the "override +allocWithZone:, -init, -retain, -release" method of creating singletons. It's virtually always unnecessary and is just adding complication for no real significant.

Instead, just write your code such that your +sharedWhatever method is how you access a singleton, and document that as the way to get the singleton instance in your header. That should be all you need in the vast majority of cases.

Chris Hanson
Is the return actually necessary here?
Phil Nash
Yes, to keep the compiler happy. Otherwise the compiler may complain that there's no return from a method with non-void return.
Chris Hanson
Funny, it doesn't for me. Perhaps a different compiler version or switches? (I'm just using the default gcc switches with XCode 3.1)
Phil Nash
This isn't just useful for singletons, but also for objects that will deallocate themselves when not needed.
Casebash
A: 

Nathan, how will returning a singleton from -init work? -init is an instance method. In other words, to call it, someone will be allocating memory each time, like [[ClassName alloc] init], which isn't ideal -- it's a waste of memory.

For the singleton pattern, you surely want a class method, not an instance method, to return the singleton, e.g. a method like +sharedMyClass.