comp.lang.ada
 help / color / mirror / Atom feed
From: dmitry@elros.cbb-automation.de (Dmitry A. Kazakov)
Subject: Re: Merits of re-dispatching [LONG]
Date: Fri, 15 Feb 2002 15:43:44 GMT
Date: 2002-02-15T15:43:44+00:00	[thread overview]
Message-ID: <3c6d1f05.23586750@News.CIS.DFN.DE> (raw)
In-Reply-To: 3C6C24A1.2633705@avercom.net

On Thu, 14 Feb 2002 15:57:05 -0500, Tucker Taft <stt@avercom.net>
wrote:

>"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.

I consider class-wide types as the major advance in OO in recent
years, but it is another issue (:-)).

>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.

This resembles the example of Nick Roberts. Of course, such small
examples have little to do with real systems, so it is had to judge.
But I think that here there are [should be (:-))] alternatives to
redispatching as well.

1. Methodically, if we are going to override Put, then we honestly
believe that the place where it displays its output, is a property of
the type. Thus it would be logical to have:

type T (Output : access Display'Class) is ...;

Display is some type representing the variety of output devices. then
Put could be made class-wide:

procedure Put (X : T'Class) is
   Text : constant String := Image (X); -- Dispatch on representation
begin
   Write (Output, Text); -- Dispatch on devices
end Put;

2. If it is not a property of the type, then Put could have an
additional parameter:

procedure Put (X : T'Class; Output: in out Display'Class) is
   Text : constant String := Image (X); -- Dispatch on representation
begin
   Write (Output, Text); -- Dispatch on devices
end Put;

Only if multiple implementations of Put cannot be factored out as a
set of types [an OO-fundamentalist would claim that it is always
possible, but I am not so sure], then we are in trouble. Anyway Ada 95
supports redispatching without implicit conversion to T'Class.

>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.

Amen! (:-))

>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



      reply	other threads:[~2002-02-15 15:43 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
2002-02-15 15:43   ` Dmitry A. Kazakov [this message]
replies disabled

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