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 Eiffels exception-handling scheme lies the principleat first an apparent platitude, but violated by many existing mechanismsthat 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:
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 Murphys law, and ensuring they do not affect the softwares basic safety and simplicity.
The design by contract ideas pervade the Eiffel method. In addition to the applications just mentioned, they have two particularly important consequences:
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.
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 nameA, B, and so on in the examplecan 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 |