Overriding methods using categories in Objective-C
Asked Answered
C

4

90

Can I use a class category to override a method that is already implemented using a category? Like this:

1) Original method

-(BOOL) method {
  return true;
}

2) Overrided method

-(BOOL) method {
  NSLog(@"error?"); 
  return true; 
}

Will this work, or is this illegal?

Carley answered 11/3, 2011 at 11:42 Comment(0)
B
152

From Apple documentation:

Although the Objective-C language currently allows you to use a category to override methods the class inherits, or even methods declared in the class interface, you are strongly discouraged from doing so. A category is not a substitute for a subclass. There are several significant shortcomings to using a category to override methods:

  • When a category overrides an inherited method, the method in the category can, as usual, invoke the inherited implementation via a message to super. However, if a category overrides a method that exists in the category's class, there is no way to invoke the original implementation.

  • A category cannot reliably override methods declared in another category of the same class.

    This issue is of particular significance because many of the Cocoa classes are implemented using categories. A framework-defined method you try to override may itself have been implemented in a category, and so which implementation takes precedence is not defined.

  • The very presence of some category methods may cause behavior changes across all frameworks. For example, if you override the windowWillClose: delegate method in a category on NSObject, all window delegates in your program then respond using the category method; the behavior of all your instances of NSWindow may change. Categories you add on a framework class may cause mysterious changes in behavior and lead to crashes.

Bozarth answered 11/3, 2011 at 11:57 Comment(11)
Thank you but I already know that. I just wonder that my case is legal or not. My case is a little bit difference from documents. :)Carley
Why it is different ? The doc says that it is legal IF the original method is not in a category, but strongly discouraged. Then you can do it...Obelize
My case is overrided method is copied from original. And just add logging routine. I wonder this is illegal. If 2 methods are different with each other clearly, I do not coding that. My adding routine is just logging routine.Carley
If you know exactly what the original method do, it is ok, otherwise you can miss something... An other method is to subclass the class and the method and calling the super method, but it's only work for your code that used this new class.Obelize
Thank you for advice. I am poor in this language. I got new information from you.Carley
Is it correct to override in Category method declared and implemented in Category of super class?Reseau
I think yes ! You sub class will override the parent class.Obelize
I have done this several times with without experiencing any issue. I had to do this in order to customize some aspects of an app which descended from another (some sort of a new target of an application, but not quite the same thing and not very easy to solve with a new target): using cateogories, I am able to keep the same code when it is needed by importing mainclass.h, and instead use the new methods by importing mainclass+category.hDilworth
"My case is overrided method is copied from original" <- that's a concern. You should never copy any code - you will struggle to change or maintain it later on. Subclass and call super in your overridden implementation. I know you asked that 3 years and definitely know that by now if you're still in professional software, but noted for the benefit of other readers.Copperplate
The link is broken, is this the new version? developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…Ablepsia
I think that documentation is outdated. You need to update this answer.Tortuga
O
18

You can do this by adapting Class Cluster approach, or using methods swizzling technique.

Otherwise, the behavior of two or more categorized methods is undefined

Olympe answered 11/3, 2011 at 12:8 Comment(0)
D
9

Old documentation link is dead; best replacement I could find was here: Apple Docs:

Avoid Category Method Name Clashes

Because the methods declared in a category are added to an existing class, you need to be very careful about method names.

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. This is less likely to be an issue if you’re using categories with your own classes, but can cause problems when using categories to add methods to standard Cocoa or Cocoa Touch classes.

It's Apple using a lighter touch, but the main point is the same: you invite disaster, because the unpredictable behavior is silent.

Doak answered 20/10, 2015 at 1:25 Comment(0)
M
2

It’s important to note that a category can also be used to override existing methods in the base class (e.g., the Car class’s drive method), but you should never do this. The problem is that categories are a flat organizational structure. If you override an existing method in Car+Maintenance.m, and then decide you want to change its behavior again with another category, there is no way for Objective-C to know which implementation to use. Subclassing is almost always a better option in such a situation.

From this tutorial, http://rypress.com/tutorials/objective-c/categories

Merozoite answered 6/3, 2015 at 12:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.