11.6 Categories

Similar to class helpers in Object Pascal, Objective-C has Categories. Categories allow to extend classes without actually creating a descendant of these classes. However, Objective-C categories provide more functionality than a class helper:

  1. In Object Pascal, only one helper class can be in scope (the last one). In Objective-C, multiple categories can be in scope at the same time for a particular class.
  2. In Object Pascal, a helper method cannot change an existing method present in the original class (but it can hide a method). In Objective-C, a category can also replace existing methods in another class rather than only add new ones. Since all methods are virtual in Objective-C, this also means that this method changes for all classes that inherit from the class in which the method was replaced (unless they override it).
  3. Object Pascal helpers cannot be used to add interfaces to existing classes. By contrast, an Objective-C category can also implement protocols.

The definition of an objective-C class closely resembles a protocol definition, and is started with the objccategory keyword:

_________________________________________________________________________________________________________
Category type

 --objccategory -|---------------------------------|-------
                -external--|---------------------- heritage-
                         -name - string constant-
----category method list --end ----------------------------------------

--heritage -(- Objective Class type identifier|protocol type identifier-- )-----
                                     ---------, ----------

--category method list|--method definition----------------------------
                   |                 -reintroduce -|  |
                   |--------------------------------|
___________________________________________________________________

Note again the possibility of an alias for externally defined categories: Objective-C 2.0 allows an empty category name. Note that the reintroduce modifier must be used if an existing method is being replaced rather than that a new method is being added.

When replacing a method, calling “inherited” will not call the original method of the class, but instead will call the parent class’ implementation of the method.

The following is an example of a category definition:

MyProtocol = objcprotocol  
  procedure protocolmethod; message ’protocolmethod’;  
end;  
 
MyCategory = objccategory(NSObject,MyProtocol)  
  function hash: cuint; reintroduce;  
  procedure protocolmethod; // from MyProtocol.  
  class procedure newmethod; message ’newmethod’;  
end;

Note that this declaration replaces the Hash method of every class that descends from NSObject (unless it specifically overrides it).