Professional C__ - Marc Gregoire [47]
FIGURE 3-9
A biologist looking at this hierarchy may be disappointed — a penguin isn’t really in the same family as a dolphin. However, it underlines a good point — in code, you need to balance real-world relationships with shared functionality relationships. Even though two things might be very closely related in the real world, they might have a not-a relationship in code because they really don’t share functionality. You could just as easily divide animals into mammals and fish, but that wouldn’t factor any commonality to the superclass.
Another important point is that there could be other ways of organizing the hierarchy. The preceding design is organized mostly by how the animals move. If it were instead organized by the animals’ diet or height, the hierarchy could be very different. In the end, what matters is how the classes will be used. The needs will dictate the design of the object hierarchy.
A good object-oriented hierarchy accomplishes the following:
Organizes classes into meaningful functional relationships
Supports code reuse by factoring common functionality to superclasses
Avoids having subclasses that override much of the parent’s functionality, unless the parent is an abstract class.
Multiple Inheritance
Every example so far has had a single inheritance chain. In other words, a given class has, at most, one immediate parent class. This does not have to be the case. Through multiple inheritance, a class can have more than one superclass.
Figure 3-10 shows a multiple inheritance design. There is still a superclass called Animal, which is further divided by size. A separate hierarchy categorizes by diet, and a third takes care of movement. Each type of animal is then a subclass of all three of these classes, as shown by different lines.
FIGURE 3-10
In a user interface context, imagine an image that the user can click on. This object seems to be both a button and an image so the implementation might involve subclassing both the Image class and the Button class, as shown in Figure 3-11.
FIGURE 3-11
Multiple inheritance can be very useful in certain cases, but it also has a number of disadvantages that you should always keep in mind. Many programmers dislike multiple inheritance. C++ has explicit support for such relationships, though the Java language does away with them altogether. There are several reasons to which multiple inheritance critics point.
First, visualizing multiple inheritance is complicated. As you saw in Figure 3-10, even a simple class diagram can become very complicated when there are multiple hierarchies and crossing lines. Class hierarchies are supposed to make it easier for the programmer to understand the relationships between code. With multiple inheritance, a class could have several parents that are in no way related to each other. With so many classes contributing code to your object, can you really keep track of what’s going on?
Second, multiple inheritance can destroy otherwise clean hierarchies. In the animal example, switching to a multiple inheritance approach means that the Animal superclass is less meaningful because the code that describes animals is now separated into three separate hierarchies. While the design illustrated in Figure 3-10 shows three clean hierarchies, it’s not difficult to imagine how they could get messy. For example, what if you realize that not only do all Jumpers move in the same way, they also eat the same things? Because there are separate hierarchies, there is no way to join the concepts of movement and diet without adding yet another subclass.
Third, implementation of multiple inheritance is complicated. What if two of your superclasses implement the same behavior in different ways? Can you have two superclasses that are themselves a subclass of a common superclass? These possibilities complicate the implementation because structuring such intricate relationships in code is difficult both for the author and a reader.
The reason that other languages can leave out multiple inheritance is that it is usually avoidable. By