In a message dated Mon, 30 Sep 2002, Michael G Schwern writes:

> On Mon, Sep 30, 2002 at 06:04:28PM -0700, David Whipp wrote:
> > On a slightly different note, if we have interfaces then I'd really
> > like to follow the Eiffel model: features such as renaming methods
> > in the derived class may seem a bit strange; but they can be useful
> > if you have have name-conflicts with multiple inheritance.
>
> I'm not familiar with the Eiffel beyond "it's the DBC language and it's
> French", but wouldn't this simply be covered by aliasing?

No, because this only gives you a second name for the method, it does not
obliterate the meaning of the first.  The example Damian uses in his OO
class (when he discusses Class::Delegation) is a Car which inherits from
Vehicle (which has an action C<method drive(int $speed)>, which causes the
car to move) and also inherits from MP3_Player (which has an accessor
C<method drive(int $id)> which sets which media spindle to use).

It's incorrect to use just the C<Vehicle::drive()> method, it's incorrect
to use just the C<MP3_Player::drive()> method, it's incorrect to call both
(vehicular acceleration would cause the MP3 player to change disks).  You
need both capabilities, but you need them separately.

You want something like

  class Car is Vehicle renames(drive => accel)
            is MP3_Player renames(drive => mp3_drive);

Either of those renamings is, of course, optional, in which case drive()
refers to the non-renamed one when referring to a Car object.

But later on, if some code does

  Vehicle $mover = getNext(); # returns a Car
  $mover.drive(5);

It should call C<Vehicle::drive()> on C<$mover>, that is,
C<$mover.accel()>.

See why aliasing doesn't solve this?

It can get more complicated, too.  Say you want to do this (I don't know
if this will be possible, but it could be):

  class DoublyLinkedList is LinkedList
                         is LinkedList
                         renames($.head => $.tail,
                                 nextNode => prevNode
                                 Node::$.next => Node::$.prev);

What's going on here?  We're inheriting from C<LinkedList> twice.  The
first time, we just accept it wholesale, including its inner Node class
which contains a $.data and a $.next reference.  The second time, we
rename the $.head reference to $.tail (along with its associated method
head() to tail()), we rename its nextNode() method to prevNode(), and we
rename *its* version of the inner Node class to make $.next into $.prev.
The Node::$.data attribute is still shared.

Redefine insert() and delete() so that it deals with both the next node
and the previous node, and you're done.  If some $variable of type
LinkedList was assigned a DoublyLinkedList, a call to
C<$variable.nextNode> would call the un-redefined nextNode, which is
correct.  If you redefined *both* C<nextNode()>s, you'd probably call the
first one in that situation.  But who knows....

Supporting repeated inheritance and multiple inheritance with partial
redefinition opens a huge ball of wax as far as complicated inheritance
rules that I don't know Damian or Larry have any interest in fleshing out,
but it could be made to work.  Try *that* with aliasing.

Trey

Reply via email to