Previous Table of Contents Next


Such a rescue clause should, before returning, restore the invariant of the class so that the caller and possible subsequent retry attempts from higher up find the objects in a consistent state. As a result, the rule for an absent rescue clause (the case, of course, for the vast majority of routines in most systems) is that it is equivalent to

   rescue
       default_rescue

where procedure default_rescue comes from GENERAL, where it is defined to do nothing; in a system built for robustness, classes subject to non-explicitly rescued exceptions should redefine default_rescue (perhaps using a creation procedure, which is bound by the same formal requirement) so that it always restores the invariant.

Behind Eiffel’s exception-handling scheme lies the principle—at first an apparent platitude, but violated by many existing mechanisms—that a routine should either succeed or fail. This is all a result of the contract notion: Succeeding means being able to fulfill the contract (possibly after one or more retry); failure is the other case, which must always trigger an exception in the caller. Without this principle, it is possible for a routine to miss its contract and yet to return to its caller in a seemingly normal state. That is the worst possible way to handle an exception.

Concretely, exceptions result from the following events:

  A routine failure (rescue clause executed to the end with no retry), as just seen.
  Assertion violation, if they are monitored.
  Attempt to call a feature on a void reference: x.f (...), the fundamental computational mechanism, can only work if x is attached to an object and causes an exception otherwise.
  Developer exception, as seen next.
  Operating system signal: no memory available for a requested creation or clone (even after garbage collection has rummaged everything to find some space), arithmetic overflow (but no C/C++-like “wrong pointer address,” which cannot occur thanks to the statically typed nature of Eiffel).

It may in some cases be useful, when handling exceptions in rescue clauses, to ascertain the exact nature of the exception that got the execution there. For this, it suffices to inherit from the kernel library class EXCEPTIONS, which provides queries such as exception, giving the code for the last exception, and symbolic names (constant attributes, see section 9.10.2) for all such codes, such as No_more_memory and so on. Then by testing exception against various possibilities, one can have specific exception handling. The method strongly suggests, however, that exception-handling code should remain simple; a complicated algorithm in a rescue clause is probably a sign of abuse.

Class EXCEPTIONS also provide various facilities for fine-tuning the exception facilities, such as a procedure raise that explicitly triggers a “developer exception” with a code than can then be detected and processed.

Exception handling makes it possible to produce Eiffel software that is not just correct but robust, by planning for cases that should not normally arise, but might out of Murphy’s law, and ensuring they do not affect the software’s basic safety and simplicity.

9.8.7. Other Applications of Design by Contract

The design by contract ideas pervade the Eiffel method. In addition to the applications just mentioned, they have two particularly important consequences:

  They make it possible to use Eiffel for analysis and design. At a high level of abstraction, it is necessary to be precise too. With the exception of BON, object-oriented analysis and design methods tend to favor abstraction over precision. Thanks to assertions, it is possible to express precise properties of a system (“At what speed should the alarm start sounding?”) without making any commitment to implementation. The discussion of deferred classes (section 9.9.6) shows how to write a purely descriptive, non-software model in Eiffel, using assertions to describe the essential properties of a system without any computer or software aspect.
  Assertions also serve to control the power of inheritance-related mechanisms—redeclaration, polymorphism, and dynamic binding—and channel them to correct uses by assigning the proper semantic limits. This is reviewed in section 9.9.9.

9.9. The Inheritance Mechanism

Inheritance is a powerful and attractive technique. A look at either the practice or literature shows, however, that it is not always well applied. Eiffel has made a particular effort to tame inheritance for the benefit of modelers and software developers. Many of the techniques are original with Eiffel. Paul Dubois has written (comp.lang.python Usenet newsgroup, 23 March 1997): “There are two things that [Eiffel] got right that nobody else got right anywhere else: support for design by contract and multiple inheritance.” Everyone should understand these correct answers if only to understand how to work around the limitations in other languages.

9.9.1. Basic Inheritance Structure

To make a class inherit from another, simply use an inherit clause:

   indexing ... class D creation ...    inherit
       A
       B
       ...
   feature
       ...

This makes D an heir of A, B, and any other class listed. Eiffel supports multiple inheritance: A class can have as many parents as it needs. Later sections (see in particular 9.9.8 and 9.9.13) explain how to handle the possible conflicts created by parent features.

By default, D simply includes all the original features of A, B, and so on, to which it may add its own through its feature clauses if any. The inheritance mechanism is more flexible, allowing D to adapt the inherited features in many ways. Each parent name—A, B, and so on in the example—can be followed by a feature adaptation clause, with subclauses, all optional, introduced by keywords rename, export, undefine, redefine, and select, enabling the author A to make the best use of the inheritance mechanism by tuning the inherited features to the precise needs of D. This makes inheritance a principal tool in the Eiffel process, mentioned earlier, of carefully crafting each individual class for the benefit of its clients. The various feature adaptation subclauses are reviewed in the following sections.


Previous Table of Contents Next