问题
When designing a class hierarchy, sometimes the subclass has added a new initWithSomeNewParam
method, and it would be desirable to disable calls to the old init
method inherited from the superclass.
First of all, I've read the question here, where the proposed alternatives are either override init
to throw an exception at runtime, or override and set default values for properties. In my case, I don't wan't to provide default values, and I want to clearly indicate that the old method should not be called, and instead the new method with parameters should be used.
So the runtime exception are fine, but unless the code is debugged, there's no way for other programmers in the team to notice that the old method is no longer intended to be used.
If I'm correct, there's no way to mark a method as "private". So, apart from adding comments, is there a way to do this?
Thanks in advance.
回答1:
You can explicitly mark your init
as being unavailable in your header file:
- (id) init __unavailable;
or:
- (id) init __attribute__((unavailable));
With the later syntax, you can even give a reason:
- (id) init __attribute__((unavailable("Must use initWithFoo: instead.")));
The compiler then issues an error (not a warning) if someone tries to call it.
回答2:
To add to what @DarkDust posted, you could alternatively use UNAVAILABLE_ATTRIBUTE
- (id)init UNAVAILABLE_ATTRIBUTE;
This will throw an error when a user tries to call init
on an instance of this class.
回答3:
Flag it deprecated? Developers will be developers, you can't stop us all! ;-)
How do I flag a method as deprecated in Objective-C 2.0?
回答4:
initWith:Stuff and:OtherStuff should never be more than convenience constructors.
In that they effectively should call
self = [self init];
if(self)
{
self.stuff = Stuff;
self.other = OtherStuff;
}
so [object init] will always return an object in a predefined state, and [object initWithStuff:stuff] will return the object in the predefined state with stuff overridden.
Basically what I'm getting at is, its bad practice to discourage [object init] especially when someone subclasses your subclass in the future….
回答5:
You can sort of mark a method as "private" by defining a private extension to your class.
In your .h:
@interface MyClassName
- (void)initWithSomeNewParam:(id)param;
In your .m:
@interface MyClassName ()
- (void)init;
@end
You could also add an NSLog
statement so that when anyone is running the project with an attached XCode session, they'll see console output similar to "Please don't use init
, use initWithSomeNewParam:
instead." Note that this is the approach Apple itself has historically taken to deprecated API calls (as well as marking deprecated in their docs).
来源:https://stackoverflow.com/questions/9634256/best-way-of-preventing-other-programmers-from-calling-init