Inheritance will never cease to surprise us with the power and versatility of its mechanisms. In this chapter we have tried to get a better handle at what inheritance really means and how we can use it to our best advantage. A few central conclusions have emerged.
First, we should not be afraid of the variety of ways in which we can use inheritance. Prohibibiting multiple inheritance or facility inheritance achieves no other aim than to hurt ourselves. The mechanisms are there to help you: use them well, but use them.
Next, inheritance is for the most part a supplier's technique. It is one weapon in our arsenal of techniques for fighting our main adversaries (in particular complexity, the software developer's relentless foe). Inheritance may matter to client software as well, especially in the case of libraries, but its main goal is to help us building the thing in the first place.
Of course, all software is designed for its clients, and the client's need drive the process. A good inheritance structure is one that will offer the best service to client software: a set of interfaces and associated implementations that are complete, free from bad surprises (such as unexpected performance penalties), simple to use, easy to learn, easy to remember, extendible. To achieve these goals, the designer is free to use inheritance and other object-oriented techniques in any way he pleases. It is the result that counts.
Also remember, when designing an inheritance structure, that the goal is software construction, not philosophy. Seldom is there a single solution, or even a best one in the absolute. "Best" means best for the purposes of a certain class of client applications. This is particularly true as we move away from areas such as mathematics and fundamental computing science, where a widely accepted body of theory exists, towards business-driven application domains. To find out what class hierarchy best addresses the notion of company share, you probably need to know whether the software caters to individual investors, to a publicly traded company, to a stock broker, or to the Stock Exchange.
In a way, this is comforting. The naturalist who classifies a certain set of plants and animals must devise absolute categories. In software the equivalent only happens if you are in the business of producing general-purpose libraries (such as those covering fundamental data structures, graphics, databases). Most of the time, your aims will be more modest. You will need to design a good hierarchy, one that will satisfy the needs of a certain kind of client software.
The final lesson of this chapter generalizes a comment
made in the discussion of facility inheritance: the principal difficulty of
building class structures is not inheritance per se; it is the search for
abstractions. If you have identified valid abstractions, their inheritance
structure will follow. To find the abstractions, the guide you will use is the
guide that we follow throughout this book: the theory of abstract data types.