Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!ucbvax!ucsd!ucsbcsl!eiffel!bertrand From: bertrand@eiffel.UUCP (Bertrand Meyer) Newsgroups: comp.lang.eiffel Subject: Re: Deferred routines and name clashes Summary: The ``join'' subclause of version 2.2 provides a solution Message-ID: <135@eiffel.UUCP> Date: 1 May 89 00:53:55 GMT References: <1981@randvax.UUCP> Organization: Interactive Software Engineering, Santa Barbara CA Lines: 219 In <1981@randvax.UUCP>, florman@randvax.UUCP (Bruce Florman) accurately describes a not infrequent type of situation for which the Eiffel 2.1 notation is too complicated. The problem arises in multiple inheritance when the programmer wishes to implement without much ado a deferred routine from one parent by a compatible effective routine inherited from another. The following is a compressed version of his description, abstracting from his particular example. (An asterisk, applied to either a class or a routine, means ``deferred''. A plus means ``effective'', i.e. non-deferred.) ________ ________ | | | | | A* | f* | B+ | f+ | | | | -------- -------- ^ ^ | | | | \ / \ / \ / \ / \ / \ / \ / \ / \ / ________ | | | C+ | f+ | | -------- Let class A have a deferred routine f and class B have an effective routine, also called f, with compatible signature and specification. [Actually, if the classes have been designed separately, there is no reason why the routines should have the same name. I'll keep this assumption for the time being for consistency with Mr. Florman's example; it will be removed later.] > [Mr. Florman tries] to define an effective class C which > inherits from both A and B, where f from B provides the implementation > for the deferred f inherited from A. But the compiler > complains about a name clash, even though the name coming > from one parent has no effective definition, and the name coming from > the other parent is simply a definition of the very same deferred > routine. > > The workaround for this problem is simple, but stupid. The class > is defined as shown below. > > class C > ... > inherit > A; > B rename f as effective_f > feature > ... > f (...) is do effective_f (...) end; > ... > end -- class C > > It certainly seems pointless and inefficient that every time any of > the C routines accesses the location, it will have to go through this > glue routine. [...] I still haven't > heard from ISE whether this should be considered an implementation > dependent feature of Eiffel (maybe when people get back from Paris). [It is strongly recommended that readers refer to the original posting for a more complete discussion.] Well, ``people'' have returned from Paris (at least some of the people have) and are slowly recovering from jet lag. The problem was indeed discussed at the Eiffel User conference there and the 2.2 solution described. (One user contribution which discussed the problem was the paper by Philippe Drix of ESEO in Angers.) Note that the ``simple but stupid workaround'' described by Mr. Florman may be found in several places in the 2.1 graphics library (which fortunately will soon be history). A solution is provided in Eiffel 2.2 by the ``join'' subclause of the ``inherit'' clause. This is applicable in multiple inheritance when the programmer wishes to use an inherited effective routine as implementation for one or more inherited deferred routines, without using the ``stupid workaround'' necessary in previous releases. The solution is the following: - Make sure that, after renaming, the effective routine and all the deferred routines it is meant to implement have the same name. [In Mr. Florman's description, this was the case without renaming since both routines had the same name, f.] - This causes a name clash. - The name clash is made legal by introducing a subclause of the form ``join f'' for all deferred routines that are to be implemented by the effective routine. (In the above example and most practical cases there is only one deferred f, but the mechanism is applicable to any number.) In the above example the solution becomes: class C ... inherit A join f; B feature ... ... no special declaration is necessary ... ... end -- class C Consider now the more general case in which the original deferred and effective routines did not necessarily have the same name: ________ ________ | | | | | A* | f* | B+ | g+ | | | | -------- -------- ^ ^ | | | | \ / \ / \ / \ / \ / \ / \ / \ / \ / ________ | | | C+ | f+ | | -------- Then the declaration of C should be: class C ... inherit A join f; B rename g as f feature ... ... no special declaration is necessary ... ... end -- class C Of course, f could have be renamed rather than g, with an inheritance clause of the form inherit A rename f as g join g; B feature ... Syntactically, the ``join'' clause comes after ``rename'' and ``redefine'' if any. It is of the form join f1, f2, ... where f1, f2, ... are deferred routines in the corresponding parent class. For each routine fi listed in this subclause, the class must contain exactly one effective routine with the same name and a compatible signature/specification. (Otherwise the class is erroneous.) Then the meaning of the subclause is simple: ``Implement each fi in this class by the corresponding effective routine.'' To take the ``join'' mechanism into account, the renaming rule (see ``Object-Oriented Software Construction'', page 278, second box) should be updated as follows: |-----------------------------------------------------------------| | Renaming rule: A name clash is said to occur in a class D when | | two features inherited from respective parents B and C have the | | same name f in D (taking into account any renaming done in D). | | | | Such a name clash is only permitted in the following two cases: | | | | 1. (Sharing in repeated inheritance.) If f was defined, etc. | | [Text unchanged until ``(if it is a routine)''.] | | | | 2. (Joining deferred routines.) If the routine corresponding to | | f in C is deferred, the routine corresponding to f in D is | | effective, they have compatible specifications, and | | the ``inherit C'' clause in B contains a ``join'' subclause | | listing f. | | | | Any other name clash is illegal (and should be removed by | | renaming). | |-----------------------------------------------------------------| A more complete description of the mechanism is contained in the document ``Release 2.2 overview'', which will be posted later. Please note that fine details of the join subclause (including the keyword itself) are still subject to change. -- Bertrand Meyer bertrand@eiffel.com