The hierarchical relationship between classes is sometimes referred to as a parent-child relationship . In a parent-child relationship, the child inherits all attributes and behaviors of the parent, and it uses the parent s access specifier to control how those inherited items are available to other classes or functions.
In C++, the parent is referred to as a base class, and the child is called a derived class . In Java, the parent is the super class, and the child is the subclass . Regardless of the terms, the relationship and functionality of a parent class and child class are the same.
Defining a parent-child relationship is intuitive in many situations. For example, it is easy to see how a student is the parent of a graduate student because a graduate student has the same attributes and behaviors of a student, and then some. However, sometimes this relationship is illusive because the relationship isn t clear ”and maybe it doesn t exist at all.
Programmers use the is a test to determine if a relationship exists between classes. The is a test determines if the child is a parent. For example, a graduate student is a student. If an is a relationship makes sense, then a parent-child relationship exists and the child can inherit from the parent. If an is a relationship doesn t make sense, then a parent-child relationship doesn t exist and the child cannot inherit from the parent, as in the case of an automobile and airplane. An automobile is a(n) airplane? This is nonsense , so you shouldn t attempt to create such a relationship.
You have three ways to implement inheritance in a program: simple inheritance, multiple inheritance, and level inheritance. Each enables a class to access attributes and behaviors of another class using slightly different techniques.
Simple inheritance occurs when there is one parent-child relationship. That is, one child inherits from one parent. Simple inheritance is shown in Figure 5-1. Two classes are represented in this diagram. These are the Student class and the GradStudent class. The Student class is the parent in this relationship and is inherited by the GradStudent class, which is the child.
Inheritance occurs from the parent to the child. A parent class cannot access attributes and behavior of a child class. In Figure 5-1, the Student class cannot call the Write() and Display() members of the GradStudent class. However, the GradStudent class can call the Student class s versions of these members.
Multiple inheritance occurs when the relationship involves multiple parents and a child. In other words, the child inherits from more than one parent. This is shown in Figure 5-2. In this example, the GradStudent class inherits from both the Person class and the Student class. The Person class and the Student class are both parents to the GradStudent class, which is the child in this relationship.
The GradStudent class inherits the characteristics of a person from the Person class. These are the weight, height, and sex attributes and the Walk() and Sit() methods . You might be wondering how a graduate student walks and sits inside a program. It is difficult to image how this is done. Although we use them in this chapter for illustrative purposes, these behaviors could be programmed into a virtual reality application that shows an animated graduate student walking across campus to a class.
You must keep several factors in mind when implementing multiple inheritance:
Each class that is inherited must pass the is a test. In Figure 5-2, the graduate student must be a student and a person in order to inherit from both parents. If the graduate student fails this test, it cannot inherit from the corresponding parent.
Parent classes are independent of each other. That is, the Student class has no knowledge of the Person class, and vice versa. The Student class cannot access attributes and behaviors of the Person class because only the GradStudent class inherits from the Person class. Likewise, the Person class does not inherit from the Student class.
Inheritance occurs in one direction from the parent to the child, which is identical to simple inheritance.
Any number of parent classes can be inherited by a child class as long as they pass the is a test.
Multiple inheritance can lead to an interesting and potentially confusing issue referred to as the diamond problem. Imagine that we have a base class called IDObject , which contains an ID attribute to hold a unique ID value. Now, we derive from that class a Student and Instructor class. So far so good: We have a Student and Instructor class, both of which have inherited a unique ID attribute. Now, imagine we create a TeacherAssistant class multiple derived from Student and Instructor . This new class has two unique IDs. This is called the diamond problem because if we draw the inheritance chart, it will be shaped like a diamond. Though we can make it work, this example can lead to confusion when we want to get the ID for the TeacherAssistant class: Which one do we want? Whereas C++ supports multiple inheritance, Java and C# do not. Java and C# provide something called interfaces, which are discussed in more detail in the Multiple Inheritance in Java section, later in this chapter. As explained in that section, interfaces are different from inheritance.
Level inheritance happens when a child inherits from a parent and then becomes a parent itself to a child. This might sound a little confusing, but it becomes clear by looking at Figure 5-3, which rearranges the Person class, Student class, and GradStudent class into a level inheritance.
The Person class is a parent class that is inherited by the Student class. The Student class is a child class in the Person class “ Student class relationship. However, another parent-child relationship exists when the GradStudent class inherits the Student class. In this relationship, the Student class is the parent class, and the GradStudent class is the child class. This means that the Student class has a duel role in inheritance. It is both a child and a parent.
Each parent-child relationship is considered a level. That is, the Person class “ Student class relationship is the first level, and the Student class “ GradStudent class is the second level. You can have as many levels as required by your program; however, many programmers stop at three levels because it becomes a bit unwieldy to manage beyond three levels.
In level inheritance, the final child class, which is the GradStudent class in the previous example, inherits attributes and behaviors for all classes in the level chain. Here s how this works: The Student class inherits attributes and behaviors from the Person class. Once inherited, these attributes and behaviors are considered members of the Student class, just as if they were defined in the Student class. When the GradStudent class inherits from the Student class, the GradStudent class has access to the Student class s attributes and behavior that now include those inherited from the Person class. As you ll remember, only attributes and behaviors designated as public or protected are inherited.
Although the last child class (that is, the GradStudent class) doesn t directly inherit from the Person class, the Person class still must pass the is a test. That is, a graduate student is a person.
There is an important difference between multiple inheritance and level inheritance. In multiple inheritance, parent classes are independent of each other. In level inheritance, a parent class that is also a child class (that is, the Student class) can access other parent classes within the leveling chain.
With three options to choose from, you re probably scratching your head wondering how you will choose. Well, there isn t a magic formula that will provide you with the best choice. Instead, you ll need to use some good-old common sense and apply your knowledge of inheritance to meet your programming objectives.
Deciding when to apply simple inheritance is intuitive because you make this choice when there is only one parent-child relationship between two objects. If you have a child class that inherits a single parent class, then simple inheritance is the only way to go.
Head scratching usually occurs when a child inherits directly or indirectly from more than one parent. This is the case with the GradStudent class, which inherits from both the person class and the student class. Here you have two choices: multiple inheritance and level inheritance.
Some programmers decide which of these to use by determining if there is an is a relationship between the two parent classes. For example, is a student a person? If so, then the better choice is to use level inheritance because this maintains the natural relationship between parent classes. That is, other kinds of student classes besides GradStudent are likely to inherit the Student class and the Person class. Once the Student class inherits the Person class, all student classes inherit the Person class when they inherit the Student class. This is illustrated in Figure 5-4, where the UndergradStudent , GradStudent , and ContinuingEdStudent classes all inherit the Student class and indirectly inherit the Person class.
In contrast, multiple inheritance is the way to go when there isn t a definitive relationship between two parents. A definitive relationship is when the relationship always passes the is a test. If the relationship passes the test sometimes but fails other times, it is not a definitive relationship.
Let s say that an undergraduate student is an athlete and a writer. This means that the UndergradStudent class inherits attributes and behaviors from the Athlete class and the Writer class. However, there isn t a definitive relationship between these two parent classes. That is, an athlete may or may not be a writer, and a writer may or may not be an athlete. This is a clear case where multiple inheritance is the better choice to use in the program, as shown in Figure 5-5.