|
||||
The Precursor constructThis document describes a proposal, initially by Bertrand Meyer, to the language committee of NICE, the Nonprofit International Consortium for Eiffel. The proposal was approved by the language committee by vote in October of 1997. The Board of NICE is expected to ratify it shortly. This short document describes the mechanism informally. It is an ISE document and does not commit NICE. A companion document contains the text of the formal proposal as adopted by the NICE language committee. In ISE Eiffel the mechanism described here is available as part of release 4.2. OverviewThis is a proposal for an extension to the Eiffel language. The author takes full responsibility for the wording of the proposal and for any error or inconsistency in it. The credit for the basic invention, however, is to be shared between the following people (in alphabetical order): Roger Browne, James McKim, Bertrand Meyer, Frieder Monninger, Steve Tynor and Kim Waldén. Rationale and backgroundIn writing classes, it frequently occurs that the redefinition of a routine r must rely on the original algorithm. A typical scheme is r (arguments) is -- Redefined version do "Parent version of r" (arguments) "Some complementary actions" end although other variants also occur (for example the actual arguments might be different from the formal ones, or the complementary actions might come before rather than after the call to the original version). In the language defined by the book "Eiffel: The Language" (Prentice Hall, 1992, hereafter "ETL"), the mechanism that achieves this result is based on repeated inheritance. The redefining class inherits a second time from the parent containing the original version of r; that second inheritance clause does not redefine r, so that the original version remains available. That version will be renamed, and typically it will be neither selected nor exported. The scheme is indexing description: "A class that redefines r while using the % original A version in the redefinition" class B inherit A redefine r select r end A rename r as original_r export {NONE} all end feature r (...) is do original_r (...) other_actions end ... Other feature declarations or redeclarations end -- class B This mechanism clearly works, and has not been a major impediment to the development of large, highly successful Eiffel systems, or to the teaching of Eiffel to tens of thousands of students of all levels. It has been criticized, however, particularly on the basis of the following considerations: 1. It is a little difficult to explain to beginners. There is a discrepancy between the relative simplicity of the goal (gaining access to the original version of a redefined feature) and the heaviness of the solution, involving a new Parent clause, export, rename and select. 2. Even for non-novices, the heaviness may become a nuisance when a non-trivial inheritance structure is involved. For example B may redefine other features beyond A, or may already be a repeated descendant of A. This can make the Inheritance clause more complicated than would seem desirable. The present proposal - resulting from extensive discussions on both comp.lang.eiffel and the NICE Language Committee, initiated by a detailed posting by Roger Browne on comp.lang.eiffel in June of 1995 - is an attempt to address the issue simply and effectively. The challenge was to simplify the task at hand - providing access to the original version of a redefined feature - while respecting the following uncontrovertible obligations: Keeping the language simple. Not introducing redundancy. Not violating correctness requirements. Not violating information hiding (which excludes in particular a Smalltalk-like super mechanism). Not impairing the ability to produce efficient compilers. Not complicating in any significant way the structure of existing compilers. The result is based on the following idea: do not define the original r as a "feature of the class" B; instead, provide a limited mechanism that allows the body of a redefined routine such as r - and only such a body - to refer to the original, under a special syntax. This, we hope, achieves the goal of a minimal extension that solves one of the very few reported sore points of Eiffel development without complicating the language significantly or affecting the spirit of its design. Auxiliary effectIt has been stated that a good language extension should whenever possible solve several problems at once. One of the consequences of the "Precursor" extension described below is a slight change to the inheritance mechanism which, we think, will improve the language. (This change conforms to the semantics which was already implemented by ISE Eiffel, departing from the ETL semantics.) This secondary change is a generalization of the Join mechanism, used to merge n inherited features with n >= 2. Under the ETL semantics at most one of these features may be effective. Under the new semantics this rule is removed; any number of effective and deferred routines may be "joined" (merged) provided all the effective ones figure in Redefine clauses in the corresponding Parent parts. This appears to simplify both the semantic description of the language and its practical use, avoiding the need to undefine n-1 effective routines, artificially chosen, out of n that one may want to join. A practical note for OOSC-2 readersThe book Object-Oriented Software Construction, second edition (Prentice Hall, 1997) describes the mechanism with a small syntactic differences: it uses double braces, as in {{PARENT}}, rather than single braces as in {PARENT}. To avoid any confusion, ISE's compiler accepts both form. The single-brace form is the recommended form. The formal proposalThe precise proposal as approved by the NICE language committee appears in a separate page.
|