开发者

How can I prevent a method from being wrongly overridden

How can I prevent a method from getting overridden in a subclass, missing a call to its superclass' implementation within?.

I know calling [super methodName]; will solve my problem sometimes.

But if somebody else was to use my parent class and overrode my method, accidentally missing to call super, what can I do?

Some more explanations:

I create a viewcontroller VC1 which has a method -(void)indexDidChange:(int)index { }. I write some actions there which I need to perform every time. and I subclass this viewcontroller named as SVC1 in it I need -(void)indexDidChange:(int)index { } for doing some other actions but at the same time the VC1 -(void)indexDidChange:(int)index { } action also need to perform. So I ne开发者_C百科ed to call like,

 -(void)indexDidChange:(int)index { 
[super indexDidChange:index];
}

So I decide to change VC1 function like,

  -(void)indexDidChange:(int)index {
     [self currentIndexDidChange:(int)index];
 }

-(void)currentIndexDidChange:(int)index { }

And I need -(void)currentIndexDidChange:(int)index { } to override and prevent -(void)indexDidChange:(int)index { } from overriding.

Is it possible?


Edit: After OP rephrased the question it is clear that OP is actually NOT looking for final methods, despite the questions initial phrasing, which implied just this.

New (updated) answer to OP's question on method overriding safety:

According to your rephrased question you are not looking for protecting a method from being overridden at all, but rather worried about one of your subclasses overriding a method and accidently missing to include a call to super in its new implementation.

This however is a fairly common and widespread issue and something you're dealing with on a daily basis, without paying much attention to it.

Every Objective-C programmer is familiar with the following method, right?

- (void)dealloc {
    [iVar release], iVar = nil;
    [super dealloc]; //skipping this call to super is fatal!
}

And we al know that skipping the [super dealloc]; makes things get uncomfortable. (afaik the clang compiler issues a warning if dealloc lacks the call to super, …pretty handy.)

Despite the fact that a bad overriding of this method can have fatal consequences Apple did not choose to put any kind of security system in place here.

Instead Apple did this (as done with any other method requiring calls to super):

  • Add a note to the method's documentation:

After performing the class-specific deallocation, the subclass method should incorporate superclass versions of dealloc through a message to super

  • Expect you, the programmer, to be a grown-up and responsible for what you do. And for playing by the rules (as defined by the documentation).

Keep in mind that - (void)dealloc is by no means an exception. There are dozens and dozens of methods of this type in Cocoa. (Take just about any derivative of - (id)init, most of the KVO observing methods, etc. just to name a few.)

So what you should do is:

  1. Write a good documentation for your method. (better for your entire project, actually)
  2. Add a big loud note to your method's documentation, explaining its rules.
  3. Add a note to each of your subclasses' overridden method implementations, right above the line that's calling super, telling the reader/dev to look up documentation, when in doubt of the rules. (optional)
  4. Code responsibly. Otherwise, you shouldn't be coding in first place. It's your customers who will suffer from it, eventually.

Old (pre-rephrasing) answer on archieving pseudo-final methods:

What you are asking for is the equivalent of a final function, as known from Java or C++. Unlike Java or C++, however there are no final methods in Objective-C.

Depending on your situation there are solutions that might bring your at least near to what you're aiming for. All you'll get though is slightly better separation. You won't get any significant security from them. In Objective-C you cannot even be sure about the origin of your methods. Method swizzling allows you to exchange methods at will. With code injection you an even inject code into processes at runtime. All this is by design of Objective-C. Objective-C allows you to saw off the branch you're sitting on. Thus it demands you to act like a grown-up. As such there are no private methods either. If a method is proclaim private you as a dev are expected to behave accordingly.

Now to possible "solutions":

If only your super class if supposed to call the given (final) method anyway:

  1. Then Macmade's solution of making your method a pseudo-private method would work quite well. The downside of hiding method declarations though is, that calling your hidden method from subclasses will give you a compiler warning, basically preventing*(sic!)* you from calling it. (It will not prevent you from calling the method though. It will only avoid you from doing so, by throwing compiler warnings.)

If subclasses however are expected to call the given (final) method:

  1. Use a delegation pattern and by this only make those methods public that are allowed to be overridden.
  2. To prevent overriding at all you could use the class cluster & abstract factory patterns, which hides your implementation classes and thus preventing overriding entirely. (Apple's NSArray, NSDictionary, NSSet classes do this)

However you might notice that with Objective-C lack of protection one usually can only choose between the two: openness, protectedness, not intermix them.


You can use categories in the implementation, so your methods aren't exposed in your header file.

MyClass.m

@interface MyClass( Private )

- ( void )myMethod;

@end

@implementation MyClass( Private )

- ( void )myMethod
{}

@end

@implementation MyClass

/* ... */

@end


If you don't declare your function in the ".h file" then its not listed, I think.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜