One of the most powerful features of OO programming is, perhaps, code reuse. Structured design provides code reuse to a certain extent—you can write a procedure and then use it as many times as you want. However, OO design goes an important step further, allowing you to define relationships between classes that facilitate not only code reuse, but also better overall design, by organizing classes and factoring in commonalties of various classes. Inheritance is a primary means of providing this functionality.
Inheritance allows a class to inherit the attributes and methods of another class. This allows creation of brand-new classes by abstracting out common attributes and behaviors.
One of the major design issues in OO programming is to factor out commonality of the various classes. For example, suppose you have a Dog
class and a Cat
class, and each will have an attribute for eye color. In a procedural model, the code for Dog
and Cat
would each contain this attribute. In an OO design, the color attribute could be moved up to a class called Mammal
—along with any other common attributes and methods. In this case, both Dog
and Cat
inherit from the Mammal
class, as shown in Figure 1.14.
The Dog
and Cat
classes both inherit from Mammal
. This means that a Dog
class has the following attributes:
eyeColor // inherited from Mammal
barkFrequency // defined only for Dogs
In the same vein, Dog
object has the following methods:
getEyeColor // inherited from Mammal
bark // defined only for Dogs
When the Dog
or the Cat
object is instantiated, it contains everything in its own class, as well as everything from the parent class. Thus, Dog
has all the properties of its class definition, as well as the properties inherited from the Mammal
class.
The superclass, or parent class (sometimes called base class), contains all the attributes and behaviors that are common to classes that inherit from it. For example, in the case of the Mammal
class, all mammals have similar attributes, such as eyeColor
and hairColor
, as well as behaviors, such as generateInternalHeat
and growHair
. All mammals have these attributes and behaviors, so it is not necessary to duplicate them down the inheritance tree for each type of mammal. Duplication requires a lot more work, and perhaps more worrisome, it can introduce errors and inconsistencies.
The subclass, or child class (sometimes called derived class), is an extension of the superclass. Thus, the Dog
and Cat
classes inherit all those common attributes and behaviors from the Mammal
class. The Mammal
class is considered the superclass of the Dog
and the Cat
subclasses, or child classes.
Inheritance provides a rich set of design advantages. When you’re designing a Cat
class, the Mammal
class provides much of the functionality needed. By inheriting from the Mammal
object, Cat
already has all the attributes and behaviors that make it a true mammal. To make it more specifically a cat type of mammal, the Cat
class must include any attributes or behaviors that pertain solely to a cat.
An inheritance tree can grow quite large. When the Mammal
and Cat
classes are complete, other mammals, such as dogs (or lions, tigers, and bears), can be added quite easily. The Cat
class can also be a superclass to other classes. For example, it might be necessary to abstract the Cat
class further, to provide classes for Persian cats, Siamese cats, and so on. Just as with Cat
, the Dog
class can be the parent for GermanShepherd
and Poodle
(see Figure 1.15). The power of inheritance lies in its abstraction and organization techniques.
In most recent OO languages (such as Java, .NET, and Objective C), a class can have only a single parent class; however, a class can have many child classes. Some languages, such as C++, can have multiple parents. The former case is called single-inheritance, and the latter is called multiple-inheritance.
Note that the classes GermanShepherd
and Poodle
both inherit from Dog
—each contains only a single method. However, because they inherit from Dog
, they also inherit from Mammal
. Thus, the GermanShepherd
and Poodle
classes contain all the attributes and methods included in Dog
and Mammal
, as well as their own (see Figure 1.16).
Consider a Shape
example where Circle
, Square
, and Star
all inherit directly from Shape
. This relationship is often referred to as an is-a relationship because a circle is a shape, and a square is a shape. When a subclass inherits from a superclass, it can do anything that the superclass can do. Thus, Circle
, Square
, and Star
are all extensions of Shape
.
In Figure 1.17, the name on each of the objects represents the Draw
method for the Circle
, Star
, and Square
objects, respectively. When we design this Shape
system, it would be very helpful to standardize how we use the various shapes. Thus, we could decide that if we want to draw a shape, no matter what shape, we will invoke a method called draw
. If we adhere to this decision, whenever we want to draw a shape, only the Draw
method needs to be called, regardless of what the shape is. Here lies the fundamental concept of polymorphism—it is the individual object’s responsibility, be it a Circle
, Star
, or Square
, to draw itself. This is a common concept in many current software applications, such as drawing and word processing applications.
3.14.83.193