Learn Objective-C, Objects (Part 6): Inheritance — Some Loose Ends


As previously before, it is very possible (and often encouraged) to override inherited methods to provide a more meaningful implementation. The exact method to invoke (the original or the overriding version) is determined by the class of the receiver of the message at runtime. It is still possible to invoke the original method by sending a call to super. This can be demonstrated by overriding the dealloc method, inherited from NSObject. To demonstrate, add the following code:

  1. // Fraction.m
  2. - (void)dealloc {
  3.     numerator = 0;
  4.     denominator = 0;
  5.     [super dealloc];
  6. }

This method does very little, except to call NSObject’s dealloc method when Fraction’s is called (We are also setting the ivars to zero). dealloc is a method related to memory management; basically it involves releasing memory held by objects. Because Fraction does not contain any objects as ivars, we don’t actually have anything to release.

We can use the same skeletal implementation in MixedNumber, where we simply call Fraction,’s dealloc, which in turn calls NSObject’s.

  1. // MixedNumber.m
  2. - (void)dealloc {
  3.     [super dealloc];
  4. }

Because MixedNumber inherits from Fraction, whatever gets released by Fraction is also released by by MixedNumber. As a matter of fact, if you forget to include [super dealloc]; in your dealloc method, you will get a compiler warning.

A later lesson will focus on categories, which allow you to add methods to a class, including classes you don’t have access to the code for, such as Apple’s own Foundation and UIKit classes.

Note that it is not possible to override ivars; however, as MixedNumber shows, it quite easy to add a new ivar. In addition, any ivars (well, almost any ivar; there are certain privacy controls, although they are rarely used) that a superclass declares are directly accessible in the subclass.

There is one pitfall involving inherited ivars, and it has to do with pointers. If you do a direct assign, such as subclassVar = superclassVar;, the former is simply a pointer (assuming that both are objects) to the superclass’s ivar, which means that if it gets freed or changed in the superclass, then the same will happen in the subclass. The solution (assuming that the above is undesired, as it usually is) is to declare a @property with retain as one of the parameters, as in

@property ([nonatomic][3], [retain][4]) NSString *myString;

in the header file of the class. Note that retain can only be applied to a property for an object, but remember that primitive types are not passed as pointers anyway, so the above issue does not exist.

Abstract Classes

There exist (and you can create) classes that are not designed to be used on their own, but merely as an object to be subclassed. For example, you will almost never create an NSObject—you’ll use a subclass. NSObject, therefore, is an abstract class.

A variant is a class cluster, such as Foudation’s NSNumber, which is what you’d create—but in fact, behind the scenes there are a number of subclasses of NSNumber that hold different types of numbers. You don’t interact with these subclasses, but only with NSNumber. These classes, along with NSNumber, for the class cluster.

This post is part of the Learn Objective-C in 24 Days course.

Author: Feifan Zhou