Objective-C Inheritance
In the chapter entitled An Overview of Objective-C Object Oriented Programming we covered the basic concepts of object-oriented programming and worked through an example of creating a new class using Objective-C. In that example, our new class was derived from the NSObject base class and as such inherited a number of traits from that parent class. In this chapter we will explore the subject of inheritance in greater detail.
Inheritance, Classes and Subclasses
The concept of inheritance brings something of a real-world view to programming. It allows a class to be defined that has a certain set of characteristics (such as methods and instance variables) and then other classes to be created which are derived from that class. The derived class inherits all of the features of the parent class and typically then adds some features of its own.
By deriving classes we create what is often referred to as a class hierarchy. The class at the top of the hierarchy is known as the base class or root class and the derived classes as subclasses or child classes. Any number of subclasses may be derived from a class. The class from which a subclass is derived is called the parent class.
Classes need not only be derived from a root class. For example, a subclass can also inherit from another subclass with the potential to create large and complex class hierarchies.
In Objective-C a subclass can only be derived from a single direct parent class. This is a concept referred to as single inheritance.
An Objective-C Inheritance Example
As with most programming concepts the subject of inheritance in Objective-C is perhaps best illustrated with an example. In the An Overview of Objective-C Object Oriented Programming we created a class called BankAccount designed to hold a bank account number and corresponding current balance. The class contained both instance variables and instance methods. The interface and implementation declarations for this class are reproduced below:
@interface BankAccount: NSObject { double accountBalance; long accountNumber; } -(void) setAccount: (long) y andBalance: (double) x; -(void) setAccountBalance: (double) x; -(double) getAccountBalance; -(void) setAccountNumber: (long) y; -(long) getAccountNumber; -(void) displayAccountInfo; @end @implementation BankAccount -(void) setAccount: (long) y andBalance: (double) x; { accountBalance = x; accountNumber = y; } -(void) setAccountBalance: (double) x { accountBalance = x; } -(double) getAccountBalance { return accountBalance; } -(void) setAccountNumber: (long) y { accountNumber = y; } -(long) getAccountNumber { return accountNumber; } -(void) displayAccountInfo { NSLog (@"Account Number %i has a balance of %f", accountNumber, accountBalance); } @end
As we can see from the declaration, this class is a subclass of the NSObject base class and contains a number of instance variables and instance methods. Though this is a somewhat basic class it does everything necessary if all you need it to do is store an account number and account balance. Suppose, however, that in addition to the BankAccount class you also needed a class to be used for savings accounts. A savings account will still need to hold an account number and a current balance and methods will still be needed to access that data. One option would be to create an entirely new class the duplicates much of the functionality of the BankAccount class together with the new features required by a savings account. A more efficient approach would be to create a new class that is a subclass fo the BankAccount class. The class will then inherit all the features of the BankAccount class but can then be extended to add the additional functionality required by a savings account.
To create a subclass of BankAccount that we will call SavingsAccount we simply write the appropriate interface and implementation structure, this time specifying BankAccount instead of NSObject as the parent class (inheritance passes down through all levels of the class hierarchy so SavingsAccount will still inherit from NSObject via the BankAccount parent class):
@interface SavingsAccount: BankAccount { } @end @implementation SavingsAccount @end
Note that although we have yet to add any instance variables or methods, the class has actually inherited all the methods and variables of the parent BankAccount class. We could, therefore, create an instance of the SavingAccount class and set variables and call methods in exactly the same way did with the BankAccount class in An Overview of Objective-C Object Oriented Programming. That said we haven't really achieved anything unless we actually take steps to extend the class.
Extending a Subclass
So far we have been able to create a subclass that contains all the functionality of the parent class (including the functionality the parent class inherited from its parent class and so on). In order for this exercise to make sense we now need to extend the subclass so that it has the features we need to make it useful for storing savings account information. To do this, we simply add the instance variables and methods that provide the new functionality, just as we would for any other class we might wish to create: