Specialization, Extension, and Inheritance |
A complete PDF version of the text book is now available. The PDF version is an almost complete subset of the HTML version (where only a few, long program listings have been removed). See here. |
After we have discussed class specialization in Chapter 25 and class extension in Chapter 26 we will now turn our interest towards inheritance. Inheritance is a mechanism in an object-oriented programming language mechanism that supports both class specialization and class extension.
This section is about inheritance in general. Inheritance in C# is the topic of Chapter 28.
|
27.1. Inheritance
Contents Up Previous Next Slide Annotated slide Aggregated slides Subject index Program index Exercise index
When a number of classes inherit from each other a class graph is formed. If, for instance, both class B and C inherit from class A we get the graph structure in Figure 27.1. Later in this section, in Section 27.4, we will discuss which class graphs that make sense.
If a class B inherits the variables and operations from another class, A, we say that B is a subclass of A. Thus, in Figure 27.1 both B and C are subclasses of A. A is said to be a superclass of B and C.
Figure 27.1 Two classes B and C that inherit from class A |
In the class graph shown in Figure 27.1 the edges are oriented from subclasses to superclasses. In other words, the arrows in the figure point at the common superclass.
In Figure 27.1 the members (variables and operations) of class A are also variables in class B and C, just as though the variables and operations were defined explicitly in both class B and C. In addition, class B and C can define variables and operations of their own. The inherited members from class A are not necessarily visible in class B and C, see Section 27.3. In essence, inheritance is a mechanisms that brings a number of variables and operations from the superclass to the subclasses.
Alternatively, we could copy the variables and operations from class A and paste them into class B and class C. This would, roughly, give the same result, but this approach is not attractive, and it should always be avoided. If we duplicate parts of our program it is difficult to maintain the program, because future program modifications must be carried out two or more places (both in class A, and in the duplications in class B and C). We always go for solutions that avoid such duplication of source program fragments.
When we run a program we make instances of our classes A, B and C. B and C have some data and operations that come from A (via inheritance). In addition, B and C have variables and operations of their own. Despite of this, an instance of class B is one single object, without any A part and B part. Thus, in an instance of class B the variables and operations of class A have been merged with the variables and operations from class B. In an instance of B there are very few traces left of the fact that class B actually inherits from class A.
The observations from above are summarized below. The situation described above, and illustrated in Figure 27.1
|
27.2. Interfaces to clients and subclasses
Contents Up Previous Next Slide Annotated slide Aggregated slides Subject index Program index Exercise index
The client interface of a class (say class A in Figure 27.2) is defined by the public members. This has been discussed in Section 11.1. In Figure 27.2 the client interface of class A is shown as number 1.
The client interface of a class B (which is a subclass of class A) is extended in comparison with the client interface of class A itself. The client interface of class B basically includes the client interface of class A, and some extra definitions given directly in class B. The client interface of class B is shown as number 3 in Figure 27.2.
When inheritance is introduced, there is an additional kind of interface to take care of, namely the interfaces between a class and its subclasses. We call it the subclass interface. Interface number 2 in Figure 27.2 consists of all variables and operations in class A which are visible and hereby applicable in class B. Similarly, the interface numbered 4 is the interface between class B and its subclasses.
Figure 27.2 Interfaces between A, B, their client classes, and their subclasses
|
27.3. Visibility and Inheritance
Contents Up Previous Next Slide Annotated slide Aggregated slides Subject index Program index Exercise index
Most object-oriented programming languages distinguish between private, protected and public variables and operations. Below we provide a general overview of these kinds of visibility.
|
In Section 28.6 we refine the description of the visibility modifiers relative to C#.
27.4. Class hierarchies and Inheritance
Contents Up Previous Next Slide Annotated slide Aggregated slides Subject index Program index Exercise index
When a number of classes inherit from each other a class graph is defined. Class graphs were introduced in Section 27.1. Below we show different shapes of class graphs, and we indicate (by means of color and text) which of them that make sense.
Figure 27.3 Different graph structures among classes |
A tree-structured graph, as shown to the left in Figure 27.3 makes sense in all object-oriented programming languages. In Java and C# we can only construct tree structured class graphs. This is called single-inheritance because a class can at most have a single superclass.
Multiple inheritance is known from several object-oriented programming language, such as C++, Eiffel, and CLOS. Compared with single inheritance, multiple inheritance complicates the meaning of an object-oriented program. The nature of these complications will be discussed in Section 27.5.
Repeated inheritance is allowed more rarely. Eiffel allows it, however. It can be used to facilitate replication of superclass variables in subclasses.
Cyclic class graphs, as shown to the right in Figure 27.3 are never allowed.
27.5. Multiple inheritance
Contents Up Previous Next Slide Annotated slide Aggregated slides Subject index Program index Exercise index
In this section we dwell a little on multiple inheritance. Both relative to class specialization (see Chapter 25) and class extension (see Chapter 26) it can be argued that multiple inheritance is useful:
|
In Figure 25.4 the overlapping extensions of the classes CheckAccount, SavingsAccount and LotteryAccount indicate that there may exist a single object, which is a CheckAccount, a SavingsAccount, and a LotteryAccount.
When we in Section 26.2 discussed the extension of class Point2D to class Point3D it could have been the case that it was useful to extend class Point3D from an additional superclass as well.
Let us now briefly argue why multiple inheritance is difficult to deal with. In Figure 27.4 we have sketched a situation where class C inherits from both class A and class B. Both A and B have a variable or an operation named x. The question is now which x we get when we refer to x in C (for instance via C.x if x is static).
Figure 27.4 Class B is a subclass of class A |
In general, the following problems and challenges can be identified:
|
Notice that some of these problems and challenges are slightly overlapping.
This ends the general discussion of inheritance. The next chapter is also about inheritance, as it relates to C#. The discussions of multiple inheritance is brought up again, in Chapter 31, in the context of interfaces.