Replicated inheritance revisited. 
Author Message
 Replicated inheritance revisited.

A recent thread here in comp.lang.eiffel touched on the problems with
replicated inheritance. At it's core lies the following example
(quoted from http://www.*-*-*.com/

--- begin quote
First of all, let's define a standard inheritance structure so that we
can talk about the issues without too much verbal overhead.

      A
     / \
    B   C
     \ /
      D

Let's [further] assume that A defines a feature f that is redefined in
B and C, and replicated in D. This gives the following features in
every class:

A: f
  B: f (inherited from A and redefined)
  C: f (inherited from A and redefined)
  D: fb (inherited and renamed from B)
     fc (inherited and renamed from C, then selected over fb)

(Note for non-Eiffelists: for purposes of this discussion, you can
assume that a "feature" is just a member function.)

Let's further assume the following declarations:

a: A
  b: B
  c: C
  d: D

 and the following instructions:

  !!d             -- Create an object of type D
  b := d; c := d  -- Assign it to entities b and c of intermediate
types
  a := d          -- Assign it to entity a of the root type.

--- end quote

It then points out the problem that occurs when a feature expecting a
B object receives a D object that uses fc and may not satisfy B's
contract. (If people want to see a concrete example, I can cook one
up.)

The proposed alternatives boil down to attempts to dynamically select
features based on the type of the object vs the type of the reference.

This proposal is, in my opinion also fatally flawed. In the proposed
solution, When a D object is assigned to a B reference, then b.f will
call B's implementation. But what if that feature violates D's
contract, say invalidating its invariant? Remember, D select's C's
functionality, which is tied to a different contract.

Inheritance of implementation (as discussed in another recent thread)
might offer one out. If in the example above, D inherited B's
implementation but not it's interface, then the assignment
   b := d
could not occur and the whole issue is sidestepped.

Another possibility is to have the select of C's features over B's
cause D to be an "improper" subtype of B, again violating the
assignment.

Both of these alternatives depend on making the problematic assignment
illegal, which frankly appears to be the only right course of action
open, because it's relatively easy to construct scenarios where B's
contract is in conflict with D's, and vice versa.

Thoughts?

Greg C



Sun, 26 Dec 2004 03:09:43 GMT  
 Replicated inheritance revisited.


Quote:
> A recent thread here in comp.lang.eiffel touched on the problems with
> replicated inheritance. At it's core lies the following example
> (quoted from
> http://efsa.sourceforge.net/cgi-bin/view/Main/ReplicatedInterfaceInhe...

> --- begin quote
[snip]
> --- end quote

> It then points out the problem that occurs when a feature expecting a
> B object receives a D object that uses fc and may not satisfy B's
> contract. (If people want to see a concrete example, I can cook one
> up.)

I think I would like to see one, where it cannot be blamed on the
author of the D class!

Quote:
> The proposed alternatives boil down to attempts to dynamically select
> features based on the type of the object vs the type of the reference.

Yes, plus the alternative where references to the same object may refer to
different "views".

Quote:
> When a D object is assigned to a B reference, then b.f will
> call B's implementation. But what if that feature violates D's
> contract, say invalidating its invariant?

Arguably, this is a problem for the author of D; if B's implementation of f
breaks D's contract, then the author was at fault for not redefining the
function, don't you think?

The inheritance interface pretty much assumes that the inheriter must know
all there is to know about the parents.

Regards,
Simon

--
Eiffel and RISC OS - Better alternatives.



Mon, 27 Dec 2004 03:58:22 GMT  
 Replicated inheritance revisited.

Quote:

> Arguably, this is a problem for the author of D; if B's implementation of f
> breaks D's contract, then the author was at fault for not redefining the
> function, don't you think?

Yes, your point is true, Simon. The programmer of D is responsible for
D's correct behaviour. So the handful of programs that encounter the
problem quite likely behave correctly -- not because the language has
guaranteed it, but because the programmer was careful.

But I think the issue is how can the language help us write correct
software. For decades programmers have carefully written correct
software without the help of static type safety, garbage collection,
DbC, etc. In languages that lack type safety, for example, the
programmer is to blame if an object of type APPLE is placed in a
variable of type PEAR. Simply observing that the programmer is to
blame for the mistake is not a good argument against having a
type-safe language. Likewise, observing that the author of D broke a
contract isn't a reason not find a way for the language to help the
author of D.

----
Peter Gummer



Mon, 27 Dec 2004 12:17:05 GMT  
 Replicated inheritance revisited.


Quote:
> A recent thread here in comp.lang.eiffel touched on the problems with
> replicated inheritance. At it's core lies the following example
> (quoted from

http://efsa.sourceforge.net/cgi-bin/view/Main/ReplicatedInterfaceInhe...
):

Quote:

> It then points out the problem that occurs when a feature expecting a
> B object receives a D object that uses fc and may not satisfy B's
> contract. (If people want to see a concrete example, I can cook one
> up.)

Yes, provide an example please.

Quote:
> The proposed alternatives boil down to attempts to dynamically select
> features based on the type of the object vs the type of the reference.

> This proposal is, in my opinion also fatally flawed. In the proposed
> solution, When a D object is assigned to a B reference, then b.f will
> call B's implementation. But what if that feature violates D's
> contract, say invalidating its invariant? Remember, D select's C's
> functionality, which is tied to a different contract.

I think the main point of suggestion is that we can
not say that D selects C`s functionality. D uses both functionalities and
can select one from them according to concrete usage place. So D should
satisfy both invariants (from B and C). Eiffel compiler can do this check
for programmer and programmer should provide correct implementation that
satisfy invariants(as Simon Willcocks said).

Quote:
> Inheritance of implementation (as discussed in another recent thread)
> might offer one out. If in the example above, D inherited B's
> implementation but not it's interface, then the assignment
>    b := d
> could not occur and the whole issue is sidestepped.

> Another possibility is to have the select of C's features over B's
> cause D to be an "improper" subtype of B, again violating the
> assignment.

If we had possibility to dynamic selection replicated parts we could wish to
use this technique and wish to have possibility for doing assignment for
every replicated part. For example, we could have several implementation for
COMPARABLE interface in one object and use this object with various
containers(like
list, array, etc...) sorted with differrent criteria. So suppressing
posibility to make assignment for every replicated part we just refuse
powerfull mechanism.

Also, I do not understand why do we need replication without support for
dynamic selection (except inheritance for reuse implementation case)?

Best Regards, Alexey Lapshin.



Mon, 27 Dec 2004 20:25:07 GMT  
 Replicated inheritance revisited.
[...]

Quote:
> But I think the issue is how can the language help us write correct
> software. For decades programmers have carefully written correct
> software without the help of static type safety, garbage collection,
> DbC, etc. In languages that lack type safety, for example, the
> programmer is to blame if an object of type APPLE is placed in a
> variable of type PEAR. Simply observing that the programmer is to
> blame for the mistake is not a good argument against having a
> type-safe language. Likewise, observing that the author of D broke a
> contract isn't a reason not find a way for the language to help the
> author of D.

> ----
> Peter Gummer

Very well said, Peter. I'd like to go further by saying that the
author of D may be in a no-win situation. What if he did not author B
and C, and C's contract is simply imcompatible with B's? In this case
the author may be forced to pick which parent he's willing to support.

At the same time, he may have no control over where his D objects will
be used. Then whose fault is it if the D object is attached to a B
reference, and the contract expected to be upheld by B's clients
isn't?

No, as Peter said, it's far better if the language and the compiler
can help us avoid these problems altogether.

Greg C



Mon, 27 Dec 2004 23:30:24 GMT  
 Replicated inheritance revisited.

Quote:
> Very well said, Peter. I'd like to go further by saying that the
> author of D may be in a no-win situation. What if he did not author B
> and C, and C's contract is simply imcompatible with B's? In this case
> the author may be forced to pick which parent he's willing to support.

Why is it neccessary to inherit from B and C in that case ? (if their
contracts are not compatible ...)

Best Regards, Alexey Lapshin.



Tue, 28 Dec 2004 00:28:33 GMT  
 Replicated inheritance revisited.


Quote:


> > Arguably, this is a problem for the author of D; if B's implementation of f
> > breaks D's contract, then the author was at fault for not redefining the
> > function, don't you think?

> Yes, your point is true, Simon. The programmer of D is responsible for
> D's correct behaviour. So the handful of programs that encounter the
> problem quite likely behave correctly -- not because the language has
> guaranteed it, but because the programmer was careful.

> But I think the issue is how can the language help us write correct
> software. For decades programmers have carefully written correct
> software without the help of static type safety, garbage collection,
> DbC, etc. In languages that lack type safety, for example, the
> programmer is to blame if an object of type APPLE is placed in a
> variable of type PEAR. Simply observing that the programmer is to
> blame for the mistake is not a good argument against having a
> type-safe language. Likewise, observing that the author of D broke a
> contract isn't a reason not find a way for the language to help the
> author of D.

Well, a language can only help us create correct software, it can't force us
to (otherwise it would have to know what we want to write before we write
it).

When you inherit, even from a single class, you undertake to maintain that
class's contract with its clients.  Otherwise, DbC is pointless.  DbC is
helping you to create correct code, because it defines what correct means.

I think the major problem with the solutions being suggested is that they
lack a simple model that programmers can get a handle on.  What we need is
that when you come across a bug in your code, your reaction should be "of
course I should have done that, it's an XYZ" instead of "why on earth would
anyone want it to do this?".  It seems pretty clear to me that whatever
approach you take to this problem, there's some way of using it that appears
odd.

Think about the statement  "x = x + 1".  To a mathematician, it makes no
sense (or it means false), but once you understand the model of assigning
the value of an expression to a variable, you can use it without a second
thought.

Simon

--
Eiffel and RISC OS - Better alternatives.



Tue, 28 Dec 2004 05:43:35 GMT  
 
 [ 7 post ] 

 Relevant Pages 

1. Replicating inheritance critique

2. self-replicating-code, self-replicating-messages

3. Public inheritance (was: Restricting inheritance)

4. Different kind of inheritance/Multiple Inheritance

5. Inheritance: Interface vs Implementation (was: Questions on inheritance)

6. Best way to replicate a string?

7. Replicate in APL2

8. Replicate Question

9. How to replicate two or more file-systems?

10. Replicated constants and frozen features

11. self-replicating code

12. Self replicating code

 

 
Powered by phpBB® Forum Software