comp.lang.ada
 help / color / mirror / Atom feed
From: "Matthew Heaney" <matthew_heaney@acm.org>
Subject: Re: How to?: Re-dispatching within an inherited method
Date: 1999/08/19
Date: 1999-08-19T00:00:00+00:00	[thread overview]
Message-ID: <37bc0730@news1.us.ibm.net> (raw)
In-Reply-To: 37BB74A8.F35560F7@hiwaay.net

In article <37BB74A8.F35560F7@hiwaay.net> , "Anthony E. Glover" 
<aeg@hiwaay.net> wrote:

> In my case, I am using pointers to objects;

Just out of curiosity: why are you using pointers?

Ada was designed so that heap use is often not necessary.  (I just want to
make sure you were aware of this, so you don't inculcate any bad habits.)

> so, I actually have to 'use' all derived type packages and then make the
> procedure call without full dot notation, such as:
>
> use A;
> use B;
>
> ...
> ...
>
>     Run_Widget( UnknownWidget.all );
>
> Where UnknownWidget is a pointer to the class wide type. Is there a better way
> of doing this?

I not convinced you really need to do this.  You don't have to with all the
packages that override primitive operations, if the parameter has a
class-wide type.

The following should work (please test this):

  A.Run_Widget (UnknownWidget.all);


One alternative (that I'm not convinced is necessary) is to make Run_Widget
a class-wide operation (a "template method"), that is implemented by calling
a private primitive operation that dispatches on the tag of the parameter.
For example:

  package P is

    type A is tagged null record;  -- or tagged private

    procedure Run_Widget (O : in out A'Class);  -- class-wide

  private

    procedure Do_Run_Widget (O : in out A);  -- primitive (and private)

  end P;


  package body P is

    procedure Run_Widget (O : in out A'Class) is
    begin
      Do_Run_Widget (O);  -- dispatches on tag of O
    end;

    procedure Do_Run_Widget (O : in out A) is
    begin
      <implementation for type A>
    end;

  end P;


  package P.Q is

    type B is new A with null record;

  private

    procedure Do_Run_Widget (O : in out B);  -- override primitive op

  end P.Q;


  package body P.Q is

    procedure Do_Run_Widget (O : in out B) is
    begin
      <implementation for type B>
    end;

  end P.Q;


Now, there is only one (public) Run_Widget operation.  When you call it:

  A.Run_Widget (UnknownWidget.all);

the internal call to Do_Run_Widget will dispatch on the tag of the param.

I you have a basic algorithm that's that same for all implementations of an
operation -- only parts on it changed based in the specific type -- then a
class-wide operation ("template method") is the way to go.

But if each overriding of the operation has a completely different
implementation, then the operation should just be a simple, public primitive
operation.

I know it must seem weird to say:

  A.Run_Widget (UnknownWidget.all);

and "really" be calling B.Run_Widget, or C.Run_Widget, but that's the nature
of the dispatching mechanism.


> If I add a new package with another derived type, then I have to go add 'uses'
> to all packages that make calls to methods of the class.

No, I don't think so: not if the object has a class-wide type.

If you want more information about template methods, so my posts to the ACM
patterns archive.

<http://www.acm.org/archives/patterns.html>

--
Matt

It is impossible to feel great confidence in a negative theory which has
always rested its main support on the weak points of its opponent.

Joseph Needham, "A Mechanistic Criticism of Vitalism"




  reply	other threads:[~1999-08-19  0:00 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-08-09  0:00 How to?: Re-dispatching within an inherited method Anthony E. Glover
1999-08-09  0:00 ` David C. Hoos, Sr.
1999-08-17  0:00   ` Matthew Heaney
1999-08-17  0:00     ` David C. Hoos, Sr.
1999-08-18  0:00       ` Matthew Heaney
1999-08-18  0:00         ` Anthony E. Glover
1999-08-19  0:00           ` Matthew Heaney [this message]
1999-08-21  0:00             ` Anthony E. Glover
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox