Introduction to Object Oriented Programming, 3rd Ed
Chapter 8
Inheritance and Substitution
Outline
- Roadmap
- Abstract idea of Inheritance
- Practical Meaning of Inheritance
- Private Public and Protected
- Inheritance is both Extension and Contraction
- The Is-a rule
- Reuse of Code, Reuse of Concept
- Syntax for Inheritance
- Trees vs Forests
- A Portion of the Little Smalltalk Hierarchy
- An Argument for Substitution
- Subclass vs Subtype
- Syntax for Overriding
- Interfaces and Abstract Classes
- Forms of Inheritance
- Specialization Inheritance
- Specification Inheritance
- Inheritance for Construction
- Inheritance for Generalization or Extension
- Inheritance for Limitation
- Inheritance for Variance
- Summary of Forms of Inheritance
- Benefits of Inheritance
- The Costs of Inheritance
- Chapter Summary
Other Material
Intro OOP, Chapter 7, outline
Roadmap
In this chapter we will start to investigate the concepts of inheritance
and substitution.
- The intuitive and practical meanings of inheritance
- The syntax used to describe inheritance and substitution
- Some of the various forms of inheritance
- The benefits and costs of inheritance
Intro OOP, Chapter 8, Slide 01
Abstract idea of Inheritance
We motivated the idea of inheritance with a hierarchy of categories:
Intro OOP, Chapter 8, Slide 02
Practical Meaning of Inheritance
-
Data members in the parent are part of the child
- Behavior defined in the parent are part of the child
Note that private aspects of the parent are part of the child,
but are not accessible within the child class.
Intro OOP, Chapter 8, Slide 03
Private, Public and Protected
There are now three levels of visibility modifiers:
- private: accessible only within the class definition
(but memory is still found in the child class, just not accessible).
- public: accessible anywhere
- protected: accessible within the class definition
or within the definition of child classes.
Note: Java interprets protected to mean accessible within same package
Intro OOP, Chapter 8, Slide 04
Inheritance is both Extension and Contraction
- Because the behavior of a child class is strictly larger than the behavior
of the parent, the child is an extension of the parent. (larger)
- Because the child can override behavior to make it fit a specialized
situation, the child is a contraction of the parent. (smaller)
This interplay between inheritance and overriding, extension and contraction,
is what allows object-oriented systems to take very general tools and
specialize them for specific projects. This interplay is ultimately
the source of a great deal of the power of OOP.
Intro OOP, Chapter 8, Slide 05
The is-a Rule
Our idealization of inheritance is captured in a simple rule-of-thumb.
Try forming the English sentences ``An A is-a B''. If it ``sounds right''
to your ear, then A can be made a subclass of B.
A dog is-a mammal, and therefore a dog inherits from mammal
A car is-a engine sounds wrong, and therefore inheritance is not natual.
but a car has-a engine.
Intro OOP, Chapter 8, Slide 06
Reuse of Code, Reuse of Concept
Why do we use inheritance? Basically there are two major motivations:
- Reuse of code. Methods defined in the parent can be made available
to the child without rewriting. Makes it easy to create new abstractions.
- Reuse of concept. Methods described in the parent can be redefined
and overridden in the child. Although no code is shared between parent
and child, the concept embodied in the definition is shared.
An example of the latter from the case study in chapter 7, all graphical
objects know how to draw.
Intro OOP, Chapter 8, Slide 07
Syntax for Inheritance
Languages use a variety of different syntax to indicate inheritance:
class Wall : public GraphicalObject -- c++
class Wall extends GraphicalObject -- Java
class Wall : GraphicalObject -- C#
(defclass Wall (GraphicalObject) () ) -- CLOS
type Wall = object (GraphicalObject) -- Object Pascal
class Wall < GraphicalObject -- Ruby
Intro OOP, Chapter 8, Slide 08
Trees vs Forests
There are two common views of class hierarchies:
-
All classes are part of a single large class hierarchy.
Thus, there is one class that is the original ancestor of all other
classes.
Smalltalk, Java and Delphi Pascal do this.
-
Classes are only placed in hierarchies if they have a relationship -
results in a forest of many small hierarchies, but no single ancestor.
C++, Objective-C, and Apple Object Pascal do this.
Intro OOP, Chapter 8, Slide 09
A portion of the Little Smalltalk Hierarchy
Intro OOP, Chapter 8, Slide 10
An Argument for Substitution
Consider the following argument:
- Instances of the subclass must possess all data areas associated with
the parent class.
- Instances of the subclass must implement, through inheritance at least
(if not explicitly overridden) all functionality defined for the parent
class. (They can also define new functionality, but that is unimportant
for the present argument).
- Thus, an instance of a child class can mimic the behavior of the parent
class. It therefore seesm reasonable that a variable declared
as a parent, should be able to hold a value generated from the child class.
Intro OOP, Chapter 8, Slide 11
The principle of substitutability is sometimes called Liskov
substitutability, since one of the first people to describe the idea
was Barbara Liskov, of MIT.
Subclass vs Subtype
Of course, the problem with this argument is that a child class can override
a method and make arbitrary changes. It is therefore useful to define
two separate concepts:
- To say that A is a subclass of B merely asserts that A is formed
using inheritance.
- To say that a is a subtype of B asserts that A preserves the
meaning of all the operations in B.
It is possible to form subclasses that are not subtypes; and (in some languages
at least) form subtypes that are not subclasses.
Intro OOP, Chapter 8, Slide 12
(We will have much more to say on this topic in a later chapter).
Syntax for Overriding
Some languages, such as C++, require that the programmer indicate
in the parent class that overriding is a potential:
class GraphicalObject {
public:
virtual void draw(); // can be overridden
};
Other languages, such as Object Pascal, require a modifier in the
child class that overriding has taken place:
type
Ball = object (GraphicalObject)
...
procedure draw; override; (* overriding has taken place *)
end
Still other languages (C#, Delphi) require indications in both parent
and child.
And some languages (Smalltalk) do not require
any indication in either parent class or child class.
Intro OOP, Chapter 8, Slide 13
Interfaces and Abstract Classes
An interface is similar to a class, but does not provide any implementation.
A child class must override all methods. A middle ground is an abstract
class. Here some methods are defined, and some (abstract methods) are
undefined. A child class must fill in the definition for abstract
methods:
abstract class Window {
...
abstract public void paint (); // child class must redefine
...
}
An interface is like an abstract class in which all methods are abstract.
In C++ an abstract method is called a pure virtual method.
Intro OOP, Chapter 8, Slide 14
Forms of Inheritance
The choices between inheritance and overriding, subclass and subtypes,
mean that inheritance can be used in a variety of different ways
and for different purposes. Many of these types of inheritance
are given their own special names. We will describe some of these
specialized forms of inheritance.
- Specialization
- Specification
- Construction
- Generalization or Extension
- Limitation
- Variance
Intro OOP, Chapter 8, Slide 15
Specialization Inheritance
By far the most common form of inheritance is for specialization.
A good example is the Java hierarchy of Graphical components in the
AWT:
- Component
- Label
- Button
- TextComponent
- CheckBox
- ScrollBar
Each child class overrides a method inherited from the parent in order
to specialize the class in some way.
Intro OOP, Chapter 8, Slide 16
Specification Inheritance
If the parent class is abstract, we often say that it is providing
a specification for the child class, and therefore it is specification
inheritance (a variety of specialization inheritance).
Example: Java Event Listeners
ActionListener, MouseListener, and so on specify behavior, but must be
subclassed.
Intro OOP, Chapter 8, Slide 17
Inheritance for Construction
If the parent class is used as a source for behavior, but the child
class has no is-a relationship to the parent, then we say
the child class is using inheritance for construction.
An example might be subclassing the idea of a Set from an existing
List class.
Generally not a good idea, since it can break the principle of
substituability, but nevertheless sometimes found in practice.
(More often in dynamically typed languages, such as Smalltalk).
Intro OOP, Chapter 8, Slide 18
Inheritance for Generalization or Extension
If a child class generalizes or extends the parent class by providing
more functionality, but does not override any method, we call it
inheritance for generalization.
The child class doesn't change anything inherited from the parent, it
simply adds new features.
An example is Java Properties inheriting form Hashtable.
Intro OOP, Chapter 8, Slide 19
Inheritance for Limitation
If a child class overrides a method inherited from the parent in a way
that makes it unusable (for example, issues an error message), then
we call it inheritance for limitation.
For example, you have an existing List data type that allows items
to be inserted at either end, and you override methods allowing insertion
at one end in order to create a Stack.
Generally not a good idea, since it breaks the idea of substitution.
But again, it is sometimes found in practice.
Intro OOP, Chapter 8, Slide 20
Inheritance for Variance
Two or more classes that seem to be related, but its not clear who
should be the parent and who should be the child.
Example: Mouse and TouchPad and JoyStick
Better solution, abstract out common parts to new parent class,
and use subclassing for specialization.
Intro OOP, Chapter 8, Slide 21
Summary of Forms of Inheritance
-
Specialization.
The child class is a special case of the parent class; in
other words, the child class is a subtype of the parent class.
-
Specification.
The parent class defines behavior that is implemented in the
child class but not in the parent class.
-
Construction.
The child class makes use of the behavior provided by the parent
class, but is not a subtype of the parent class.
-
Generalization.
The child class modifies or overrides some of the methods of the
parent class.
-
Extension.
The child class adds new functionality to the parent class, but
does not change any inherited behavior.
-
Limitation.
The child class restricts the use of some of the behavior inherited
from the parent class.
-
Variance.
The child class and parent class are variants of each other, and the
class-subclass relationship is arbitrary.
-
Combination.
The child class inherits features from more than one parent class.
This is multiple inheritance and will be the subject of a later chapter.
Intro OOP, Chapter 8, Slide 22
Benefits of Inheritance
-
Software Reuse
-
Code Sharing
-
Improved Reliability
-
Consistency of Interface
-
Rapid Prototyping
-
Polymorphism
-
Information Hiding
Intro OOP, Chapter 8, Slide 23
Cost of Inheritance
-
Execution speed
-
Program size
-
Message Passing Overhead
-
Program Complexity
This does not mean you should not use inheritance, but rather than you
must understand the benefits, and weigh the benefits against the costs.
Intro OOP, Chapter 8, Slide 24
Chapter Summary
In this chapter we have begun the exploration of inheritance,
a topic we will continue through the next several chapters.
Topics we have addressed have included the following:
- The meaning of inheritance
- The syntax used to describe inheritance and overriding
- The idea of substitution of a child class for a parent
- The various forms of inheritance
- The cost and benefits of inheritance
Intro OOP, Chapter 8, Slide 25