Both
inheritance and composition allow you to create a new type from existing types.
Typically, however, you use composition to reuse existing types as part of the
underlying implementation of the new type and inheritance when you want to
reuse the interface. Since the derived class has the base-class interface, it
can be
upcast
to the base, which is critical for polymorphism, as you’ll see in the
next chapter.
Despite
the strong emphasis on inheritance in object-oriented programming, when you
start a design you should generally prefer composition during the first cut and
use inheritance only when it is clearly necessary. (As you’ll see in the
next chapter.) Composition tends to be more flexible. In addition, by using the
added artifice of inheritance with your member type, you can change the exact
type, and thus the behavior, of those member objects at run-time. Therefore,
you can change the behavior of the composed object at run-time.
Although
code reuse through composition and inheritance is helpful for rapid project
development, you’ll generally want to redesign
your class hierarchy before allowing other programmers to become dependent on
it. Your goal is a hierarchy in which each class has a specific use and is
neither too big (encompassing so much functionality that it’s unwieldy to
reuse) nor annoyingly small (you can’t use it by itself or without adding
functionality). Your finished classes should be easily reused.