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