2

Say I have a class Parent and the child is Child1 and Child2.

I declare Parent+ParentCategory and then I declare a method:

-(void) Redraw;

Later I want the Redraw function of Child1 to be different than the Redraw function of Child2.

Can I declare Child1+Child1Category and then override the

-(void) Redraw

Can -(void)Redraw of Child1 call the function in the parent category?

Can that be done?

What would be good approach?

I know classes can inherit each other. I know protocol can extend each other. I wonder why category doesn't?

Joe
  • 15,205
  • 8
  • 49
  • 56
user4951
  • 32,206
  • 53
  • 172
  • 282
  • There was a similar question asked before http://stackoverflow.com/questions/3357282/can-i-use-a-category-to-override-a-method-which-is-itself-in-category-on-the-sup . But it doesn't answer your question of child1 category function calling the parent category. – Adithya Jun 07 '13 at 10:07

3 Answers3

4

I do not agree with the given answers:

A.: It is not true, that category's methods win against class' method. This is an implementation detail, but the behavior is not defined.

If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime.

B. But this does not matter. You neither define a method in a category that is defined in the class nor define a method in two clashing categories. The cit. simply does not apply to your case. It applies to something like this:

@interface A : NSObject
- (void)doSomething;
@end
@implementation A
- (void)doSomething {}
@end

@interface A (Addition)
- (void)doSomething;
@end
@implementation A (Addition)
- (void)doSomething {}
@end

If I understand you correct, you do not want to do this. You want something like that:

Base level:

@interface A : NSObject
@end
@implementation A
@end

@interface A (Addition)
- (void)doSomething;
@end
@implementation A (Addition)
- (void)doSomething {}
@end

This does not break the rule, because there is no method in the category, which is in the class.

Subclass level:

@interface B : A
@end
@implementation B
@end

@interface B (Addition)
- (void)doSomething;
@end
@implementation B (Addition)
- (void)doSomething {}
@end
  1. There is no clash on the level of B for the same reason as there is no clash on the level of A.

  2. Somebody might say, that there is a clash, because B inherits -doSomething from A. But this is no clash, because in this case a priority rule applies: Subclasses overwrite methods.

You can do that.

Edit:

You can check the problem simply by adding the method to the class. Would that compile? In the clashing case, it wouldn't. In your case, it would.

Amin Negm-Awad
  • 16,582
  • 3
  • 35
  • 50
  • Just a question sir: Have you tried what you are explaining above? I am writing some tests right now (Maybe that 2.00am is not the right moment to write code but i was just curious) and the code doesn't even compile complaining for "duplicate symbol". – Antonio E. Jun 07 '13 at 22:59
  • Signore, I implemented this "system" several times for predicates. And I compiled the code above. If you have a duplicate symbol error, you should do the following things: 1. Check your copy & paste. You did an error, copying and pasting the code. 2. Report, where you get the duplicate symbol. As an experienced objective-c programmer you know, that classes and categories open a seperate namespace, to get a duplicate symbol over different classes and categories is really hard. Here is a sample project: http://www.cocoading.de/webspace/CategoriesAndClasses.zip – Amin Negm-Awad Jun 08 '13 at 06:10
  • I have to clearify: With "cit." I meant the cit in your answer. The documentation cit. in my answer is not completly correct, because a method in a superclass cannot clash with a method in a subclass. – Amin Negm-Awad Jun 08 '13 at 06:17
  • Back from Sunbathing. (FINALLY SUMMER!) :) I want to add a thing, but I think it is fullfilled in nearly every case. All Bundles that add such a category to a subclass should be loaded. – Amin Negm-Awad Jun 08 '13 at 14:07
2

I will replay with a cit. from this answer:

Lets just put it this way. Don't override methods using categories, period, ever, end of answer.

The reason of this is that while it is exactly known that a category's method always win against a class method (that is, if you implement a method in a category that's already declared in the class you are extending with the category the method of the category will be called.) when you have multiple category implementing the same method which implementation takes precedence is undefined

Community
  • 1
  • 1
Antonio E.
  • 4,381
  • 2
  • 25
  • 35
0

It is not wise to use category to do this. Categories add methods to the current class. If there are multiple methods with the same name, it will replace the old one (it is NOT an override). But unfortunately it is hard to say which one is replaced. Don't do it or you may get in trouble.

And you probably can not call the method in Parent from the child category. The most proper design here is a protocol.

THE_DOM
  • 4,266
  • 1
  • 18
  • 18
onevcat
  • 4,591
  • 1
  • 25
  • 31