This site contains older material on Eiffel. For the main Eiffel page, see http://www.eiffel.com.

25.6 ONE MECHANISM, OR MORE?

The variety of uses of inheritance, evidenced by the preceding discussion, may lead to the impression that we should have several language mechanisms to cover the underlying notions. In particular, a number of authors have suggested separating between module inheritance, essentially a tool to reuse existing features in a new module, and type inheritance, essentially a type classification mechanism.

Such a division seems to cause more harm than good, for several reasons.

First, recognizing only two categories is not representative of the variety of uses of inheritance, reflected by the preceding classification. Since no one will advocate introducing ten different language mechanisms, the result will be too limitative.

The practical effect would be to raise useless methodological discussions: assume you want to inherit from an iterator class such as LINEAR_ITERATOR; should you use module inheritance or type inheritance? One can find arguments to support either answer. You will waste your time trying to decide between two competing language mechanisms; the contribution of such reflections to the only goals that count --- the quality of your software and the speed at which you produce it --- is exactly zero.

An exercise asks you to analyze our categories to try to see for each of them whether it relates more to the "module" or "type" kind.

It is also interesting to think of the consequences that such a division will have on the complexity of the language. Inheritance comes with a number of auxiliary mechanisms. Most of them will be needed on both sides:

  • Redefinition is useful both for subtyping (think of RECTANGLE redefining perimeter from POLYGON) and for module extension (the open-closed principle demands that when we inherit a module we keep the flexibility of changing what is not adapted any more to our new context --- a flexibility without which we would lose one of the main attractions of the object-oriented method).

  • Renaming is definitely useful for module inheritance. The view that presents it as inappropriate for type inheritance (see [Breu 1995]) seems too restrictive. In the modeled external system, variants of a certain notion may introduce their own special terminology, which it is often desirable for the software to respect. To take just one example, a class STATE_INSTITUTIONS used in some geographical or electoral software system might have a descendant LOUISIANA_INSTITUTIONS to reflect the peculiarities of Louisiana's political structures; then it is not unreasonable to expect that the feature counties, giving the list of counties in a state, would be renamed parishes in the descendant, since parish is what Louisianians call what the rest of the US knows as a county.

  • Repeated inheritance may occur with either form. Since we may expect that module-only inheritance will preclude polymorphic substitution, the problem of disambiguating dynamic binding, and hence for a select clause, will only arise for type inheritance; but all the other problems of repeated inheritance, in particular the qeustion of when to share repeatedly inherited features and when to replicate them, still arise.

  • As always when we introduce new mechanisms into a language, they interact with the rest, and with each other. Do we prohibit a class from both module-inheriting and type-inheriting the same class? If so, we may be just vexing developers who have a good reason to use the same class in two diferent ways; if not, we open up a whole can of new language issues --- name conflicts, redefinition conflicts and so on.

All this for the benefit of a purist's view of what inheritance should be. This view, it should be noted, is controversial. Not that there is anything wrong with controversial views per se; but one should be careful before imposing their consequences on language users --- that is to say, on everyone. Once again, the contrast with Dijkstra's original goto excommunication is striking: Dijkstra took great care to explain in detail the drawbacks of the goto instruction, based on a theory of software construction and execution, and to explain what replacements were available. In the present case, no compelling argument --- at least none that I have seen --- as to why it is "bad" to use a single mechanism to cover both module and type inheritance. Aside from blanket condemnations based on preconceived ideas of what inheritance should be (possibly valid, but limitative), there is only one serious objection to the use of a single mechanism: the extra complication that this approach imposes on the ta

In the end what all this discussion shows is that the ability to use a single inheritance mechanism for both module and type inheritance is not --- as partisans of separate mechanisms implicitly consider --- the result of a confusion of genres. It is the result of the very first decision of object-oriented software construction: the unification of module and type concepts into a single notion, the class. If we accept classes as both modules and types, then we should accept inheritance as both module accumulation and subtyping.

PREVIOUS SECTION ---- NEXT SECTION