Re: Inheritance Questions

Frank Salter <[email protected]>
Newsgroups gmane.comp.lang.eiffel.smalleiffel
Message-ID <[email protected]>
Daniel F Moisset wrote:

>On Thu, 2005-04-14 at 10:49 +0100, Frank Salter wrote:
>  
>
>>I would like to ask you to examine the following facts and consider 
>>their implications.
>>    
>>
>
>It's a very interesting problem. For theorists, but for practical
>purposes too.
>
>  
>
>>The following program compiles correctly and produces the expected output.
>>(...)
>>==============================================================
>>If the class STAFF_LIST attempts to "insert" rather than "inherit" the 
>>LINKED_LIST, the program fails to compile with the following message:
>>
>>compile test -o test
>>****** Fatal Error: Cannot pass `other' which is of type STAFF_LIST
>>into formal type COLLECTION[EMPLOYEE].
>>Line 190 column 20 in LINKED_LIST (/opt/SmartEiffel/lib/storage/collection/linked_list.e):
>>         from_collection(other)
>>                         ^     
>>Line 284 column 26 in LINKED_LIST (/opt/SmartEiffel/lib/storage/collection/linked_list.e):
>>   from_collection (model: COLLECTION[like item]) is
>>(...)      
>>    
>>
>
>The culprit here is {LINKED_LIST}.copy (line 190)
>
>    copy (other: like Current) is
>        do
>            from_collection(other)
>        end
>
>What you're trying to do clearly calls for non-conforming inheritance;
>but this example shows that it's not working properly together with
>anchors. I'm not talking about SmartEiffel (the message is perfectly
>reasonable), but the mechanism itself.
>
>LINKED_LIST conforms to COLLECTION, so "like Current" conforms to
>COLLECTION too (for LINKED_LIST and any conforming descendant). But
>here, when inserting LINKED_LIST, you got a new class where like Current
>does not conform to COLLECTION any longer...
>
>This will probably happen in any case where an expression with an like
>Current is used in a place where a non-anchored type is requested.
>This raises a lot of questions about the interaction of these two
>mechanisms (non conforming inheritance (NCI) and ¿anchors?) that should
>be researched... I don't think there's an easy answer.
>
>At this time, I think the possible answers (none satisfactory) are:
>
>a) Blame the language/compiler: "You should not be able to write (at
>LINKED_LIST) code passing an anchor to a explicitly typed parameter,
>because that forbids NCI. Bad language that allows it/Bad compiler that
>does not check it". This could be enforced at a language level, but
>being very restrictive (very legitimate uses, like from_collection,
>would be forbidden).
>
>b) Blame the library writer: "Library writers shouldn't write methods
>like that, breaking possible reuse". The whole SE/ISE/whatever library
>could be fixed to avoid this. But that doesn't mean it won't happen
>again, in developer classes. It's hard to say if the assumption that all
>classes getting the copy method from COLLECTIONS will be COLLECTIONs
>(i.e., what breaks here) is too strong or not to drop it.
>
>c) Blame the mechanism: "OK, NCI is broken, I'll just use inherit". In
>fact that was the proposed way of doing it before NCI. It's a
>possibility, but it's sad to drop an apparently nice and useful feature.
>
>d) Blame the developer: "When doing tricks like inheriting standard
>classes, things break. It's my job to fix them". That's quite true,
>essentially of classes redefining standard methods (like copy, is_equal)
>which are used everywhere. And some times you have to do some
>inheritance juggling (renaming, redefining, undefining, joining) to get
>it right. Perhaps you can do just that (redefining copy inside
>STAFF_LIST).
>
>Trying that I found another problem:
>
>    get_new_iterator: ITERATOR[E] is
>        do
>            create {ITERATOR_ON_LINKED_LIST[E]} Result.make(Current)
>        end
>
>note that no anchors are used here, but the problem repeats. So the
>problem is not the use of anchors, but the use of Current. Which makes
>sense: After inserting LINKED_LIST, Current may be now something almost,
>but not quite, completely unlike a LINKED_LIST.
>
>
>  
>
>>==============================================================
>>
>>Now if the following export clause is applied to the inherited 
>>LINKED_LIST then the compiler produces 69 messages. This
>>output is elided as all the messages are similar and originate in the 
>>library classes.
>>
>>export {COLLECTION, GENERAL, LINKED_LIST, NONE} all;
>>
>>                    {LINKED_LIST, TEST}  make, add_last, do_all
>>            end
>>(...)
>>==============================================================
>>    
>>
>
>I've crossed this problem before. Specially when porting programs from
>SE1.1 (where restricted export was the way of doing this) to SE 2.1.
>I think a single warning per-export clause instead of a warning
>per-method should be enough; perhaps an option of disabling it (given
>that it marks as faulty code that was in the suggested style up to
>recent times).
>
>  
>
>>So I would like to pose the following questions particularly to the 
>>theorists.
>>          Does the above demonstrate a missing Eiffel inheritance 
>>facility akin to "inherit" and "insert"?
>>    
>>
>
>*Another* feature will just add more incompatibilities between language
>mechanism. Look at what happened when NCI was added (The meaning of
>"Current" was broken).
>
>  
>
>>          As the above seeks to impose restrictions on the inheritance, 
>>would the use of a further facility
>>          such as "restrict" improve the ability of a compiler to work.
>>    
>>
>
>What is "restrict"?
>
>Thanks for the interesting discussion :)
>
>	Daniel
>
>PS: You should post about this to comp.lang.eiffel too...
>  
>
Thank you for your very thoughtful discussion.  In the above I intended 
to suggest that some further mechanism such as
class      STAFF_LIST
restrict   LINKED_LIST[EMPLOYEE]
might be required.  In Eiffel, the background ethos appears to be that 
all language mechanisms should be both sufficient and necessary.  I will 
settle happily for sufficient if that produces a working solution. I can 
see the possibility that a third inheritance mechanism might facilitate 
this.  However, I must leave it to the theorists to provide an answer to 
this question.  Hence the earlier posting.
I share the sentiment you expressed above (repeated below) that

"This raises a lot of questions about the interaction of these two
mechanisms (non conforming inheritance (NCI) and ¿anchors?) that should
be researched... I don't think there's an easy answer."

In OOSC2, p 824, under General Taxonomy, Meyer introduces 3 broad 
families of inheritance.  This may be indicative that 2 inheritance 
mechanisms may be insufficient to encompass fully, all the categories 
defined there.  Therefore I would ask if it has been demonstrated that 2 
mechanisms are sufficient and necessary to provide all of these 
inheritance categories for use in  programs.
As a separate but possibly relevant aside, the following class is 
currently not possible in SmartEiffel,

expanded class   TWO_DECIMAL_DIGIT_INTEGER
         insert  INTEGER

invariant  in_range : Current.in_range(10, 99);
end

I do not understand the particular difficulties that prevent such a 
class being implemented.  I am sure that the compiler team would have 
done so, if there had been a simple solution.  So I would like to ask.  
What are the difficulties?  Does the expanded inheritance mechanism, 
"insert", remove any of these?  If not, is this a demonstration that 
some other inheritance mechanism may be useful?
Regards
Frank Salter
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.