Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!uupsi!sunic!news.funet.fi!tukki.jyu.fi!sakkinen From: sakkinen@jyu.fi (Markku Sakkinen) Newsgroups: comp.lang.eiffel Subject: Re: Simple Eiffel Feature Call Question Message-ID: <1991May10.072354.7189@jyu.fi> Date: 10 May 91 07:23:54 GMT References: <5583@goanna.cs.rmit.oz.au> <1160@tetrauk.UUCP> Reply-To: sakkinen@jytko.jyu.fi (Markku Sakkinen) Organization: University of Jyvaskyla, Finland Lines: 85 In article <1160@tetrauk.UUCP> rick@tetrauk.UUCP (Rick Jones) writes: >In article <5583@goanna.cs.rmit.oz.au> ajk@wren.cs.rmit.OZ.AU (Alan Kent) writes: >> ... >>Consider three classes A, B and C where (the syntax might not be quite right) >> class A export f ... >> class B export f inherit A redefine f ... >> class C export f inherit B redefine f ... >> >>Assume Current is an instance of class C. In feature f of class B I would >>like to be able to... >>(1) Call version C of method f (the definition in the class of the object) >>(2) Call version B of method f (the definition in the current class) >>(3) Call version A of method f (the parent's definition) >> >>As I understand Eiffel, it will always do approach (1). > >Correct in the normal case, although I think your terminology is a little >confused. Yes, the intent would be clearer if both 'feature f' and 'method f' above were substituted by 'routine f'. >Approach (3) is quite easy - so I'll answer that first. This requires one of >the less obvious combinations of renaming and redefinition. In class B you >must declare: > ... [A good explanation of how (3) is indeed possible, contrary to Kent's doubt.] >Now the more difficult bit :-) Your problem statement seems to confuse the >type of a variable with the type of an object. Take for example: > ... No! Variables were not even mentioned in the original posting. You did not quote the salient paragraph in it: -The reason I would like to be able to do (2) is for recursion. I dont want my -definition of a recursive algorithm in B to be changed by some decendant class. -The only way I can think of doing this is to make f call another feature -f_secret where f_secret is not exported (and so can be recursive safely). This is a perfectly reasonable wish. I regard it as a definite defect in Eiffel (and Smalltalk and many other OOPL's) that there is _no way_ to achieve it. The following part of Jones' posting tells why even the work-around suggested above will not give absolute security - although it will work if all descendant class programmers respect the intent of 'f_secret'. >It is a basic property of Eiffel that a class cannot prevent a descendant from >redefining any of its features. This includes non-exported as well as exported >ones. There is a presumption that inheritance is used responsibly, and >assertions (especially the class invariant, which cannot be overridden, only >added to) can trap any gross violations which a descendant may try to perpetrate. >One approach to recursion or iteration where the algorithm is always the same, >but the actual operation on each loop may need to be different in descendants, >is to have the recursion feature call a local routine on each loop. This >routine would probably not be exported and can be empty, or even deferred, in >the class which defines the recursion. Descendants then only need to define >(or redefine) this routine, and it will only be required to deal with one >instance on each call. This suggestion can be relevant in several situations, but it does not help a bit in the exact problem posed by Kent. Read it as a side note. BTW, even a slight generalisation of the original problem is relevant, and a "perfect" OOPL should be able to support it: In a routine f of class B, invoke different versions of routine g (possibly _different_ from f): (1) from the (most specific) class of the current object, (2) from the same class, (3) from ancestor class. Among well-known OOPL's, the explicit class qualification possibility of C++ allows both (2) and (3). For case (3), it is clumsier than 'super' in Smalltalk and many other languages. The Eiffel way of renaming the ancestor class routine looks even clumsier in simple cases, but is probably better for reuse: e.g. if a routine can be copied (possibly with small modifications) from a class to another, unrelated class. Markku Sakkinen Department of Computer Science and Information Systems University of Jyvaskyla (a's with umlauts) PL 35 SF-40351 Jyvaskyla (umlauts again) Finland SAKKINEN@FINJYU.bitnet (alternative network address)