comp.lang.ada
 help / color / mirror / Atom feed
From: Tucker Taft <stt@avercom.net>
Subject: Re: Merits of re-dispatching [LONG]
Date: Thu, 14 Feb 2002 15:57:05 -0500
Date: 2002-02-14T20:57:06+00:00	[thread overview]
Message-ID: <3C6C24A1.2633705@avercom.net> (raw)
In-Reply-To: 3c62524f.93369796@News.CIS.DFN.DE

"Dmitry A. Kazakov" wrote:
> 
> Hi!
> 
> C++ and Ada 95 support re-dispatching, which I think is inherently
> unsafe.
> ...

Redispatching is the default in most OO languages.  In some, like
Eiffel and Java, there is no alternative.  In C++, it is possible
to explicitly prevent redispatching by using the :: operator.  By default,
if you use a reference, a pointer (e.g. "this"), or just
the virtual function name by itself, you get (re)dispatching.

In Ada 95, we chose to make static binding the default, with (re)dispatching
happening only when the actual parameter is of the classwide type (T'Class).
This was a conscious decision, and means that places where (re)dispatching
is occurring are visible to the reader, and requires some explicit intent
by the programmer.  This reduces the cases of unintentional redispatching,
and (hopefully) encourages the programmer to mention internal redispatching
as part of the semantics of the operation.

In your example, you have used redispatching in a finalization routine.
As you point out, that is an unusual time to do so, and is probably
unwise, because the descendant's finalization activity has probably already
taken place.  Hence, your example illustrates an inappropriate use
of redispatching.  On the other hand, there are many examples of appropriate
use of redispatching.  However, these all are cases where the semantics
of the routine should be explicitly idenfitied as including redispatching.

For example, consider the following:

    type T is tagged ...
    function Image(X : T) return String;  -- Return string representation of T
    procedure Put(X : T);  -- Display T on standard output; by default,
                           -- put result of (redispatch to) Image function

In this example, we have defined the "default" semantics of "Put" to
be a Text_IO.Put of a redispatching call to Image.  This would allow a programmer
to override Image only, and have the desirable effect of having Put's results altered
as well.  Here is the implementation of this "default" Put:

   procedure Put(X : T) is -- by default, put result of calling Image
   begin
       Text_IO.Put(Image(T'Class(X));
   end Put;

On the other hand, for some complex types, it may be desirable to take advantage
of the fact we are displaying on standard output, and we might create a multi-line,
nicely indented version of the display.  In that case, we would want to override
Put to not simply put out the result of calling Image.

Clearly this relationship between the Image and Put primitive operations
needs to be explicit in the spec for "T".  Otherwise, when we release a new
version, we might choose to change Put to effectively "inline" the semantics
of Image, rather than making a redispatching call.  In that case, the
programmer could choose to inherit the "Put" semantics as is while changing "Image",
but could no longer override only Image and expect Put to change "correspondingly."

This is a fairly simple example, but with a complex type, the relationships
can get very complicated.  If no redispatching is done, then all of the
operations are independent "black boxes," and they can be inherited if they
already have the desired effect, or overridden if they don't.  When redispatching
is present, the programmer needs to know the relationships between the primitive
operations, so they can make appropriate decisions about inheriting versus
overriding.

As mentioned above, in Ada 95, we chose to make static binding the default for calls
from one primitive to the next, thereby providing minimal "coupling" between
the primitives, and allowing them to be reused as black boxes.  However, we
felt it was essential that we also supported explicit redispatching, for the
cases where "pass-the-buck" semantics were appropriate, where by default
one primitive should redispatch to another, allowing a fewer number of primitives to
be overridden when extending a type.

In any case, we agree that redispatching can be the wrong thing to do, and
making it the default opens the door for unintentional coupling between
primitives, effectively requiring that a programmer see the source code
for the primitives of a parent type to determine the effect of overriding
some but not all of the primitives in a derived type.

> ...
> Is there examples where re-dispatching is really unavoidable?

If you are always willing to override all primitive operations, 
then re-dispatching is avoidable.  However, if you want to override
only some of the primitives, and rely on the others being defined
by default in terms of these, you can simplify the job of extending
a type.  But as indicated above, we certainly agree that redispatching
is part of the *visible* semantics of a primitive operation, when extending
a type.
> 
> Regards,
> Dmitry Kazakov

-- 
-Tucker Taft   stt@avercom.net   http://www.avercom.net
Chief Technology Officer, AverCom Corporation (A Titan Company) 
Bedford, MA  USA (AverCom was formerly the Commercial Division of AverStar:
http://www.averstar.com/~stt)



  parent reply	other threads:[~2002-02-14 20:57 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-02-07 10:26 Merits of re-dispatching [LONG] Dmitry A. Kazakov
2002-02-07 15:03 ` Hyman Rosen
2002-02-08  1:29   ` Matthew Heaney
2002-02-08  9:16     ` Dmitry A. Kazakov
2002-02-08 18:30       ` Hyman Rosen
2002-02-09  0:10         ` Matthew Heaney
2002-02-12  8:32         ` Dmitry A. Kazakov
2002-02-12 21:37           ` Hyman Rosen
2002-02-13  9:29             ` Dmitry A. Kazakov
2002-02-13 14:32               ` Hyman Rosen
2002-02-13 19:58           ` Dave Harris
2002-02-14 15:06             ` Dmitry A. Kazakov
2002-02-16 12:10               ` Dave Harris
2002-02-18  8:57                 ` Dmitry A. Kazakov
2002-02-18 19:47                   ` Merits of re-dispatching Dave Harris
2002-02-19  9:20                     ` Dmitry A. Kazakov
2002-02-21  5:49                       ` Hyman Rosen
2002-02-21  9:04                         ` Dmitry A. Kazakov
2002-02-21 18:17                           ` Hyman Rosen
2002-02-22  9:21                             ` Dmitry A. Kazakov
2002-02-22 16:59                               ` Hyman Rosen
2002-02-25  8:51                                 ` Dmitry A. Kazakov
2002-02-08 23:51       ` Merits of re-dispatching [LONG] Matthew Heaney
2002-02-12  9:02         ` Dmitry A. Kazakov
2002-02-07 23:40 ` Nick Roberts
2002-02-08  8:56   ` Dmitry A. Kazakov
2002-02-08  1:06 ` Matthew Heaney
2002-02-08  9:48   ` Dmitry A. Kazakov
2002-02-09  0:16     ` Matthew Heaney
2002-02-08 18:10   ` Hyman Rosen
2002-02-09  0:41     ` Matthew Heaney
2002-02-08 18:33 ` Nick Roberts
2002-02-09  4:07   ` Nick Roberts
2002-02-12 10:13   ` Dmitry A. Kazakov
2002-02-14 20:57 ` Tucker Taft [this message]
2002-02-15 15:43   ` Dmitry A. Kazakov
replies disabled

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