comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Dynamich Dispatching...
Date: Mon, 4 Oct 2004 10:02:20 +0200
Date: 2004-10-04T10:02:20+02:00	[thread overview]
Message-ID: <18qpcb693v2zz$.1es3pcrwk4eiu$.dlg@40tude.net> (raw)
In-Reply-To: cjmi3n$iat$03$1@news.t-online.com

On Sat, 2 Oct 2004 17:39:15 +0200, Rick Santa-Cruz wrote:

> I know what to understand about Dynamic Dispatching, but with the following 
> example in Ada I have some problems to understand the whole thing:
> 
> -- package Objects
> package Objects is
>  type Object is abstract tagged private;

If you plan Objects to be always constructed using a call to some
constructor function, make sure that they will:

type Object (<>) is abstract tagged private;

This will prevent declarations like:

X : Derived_Object; -- No initial value given

>  type Object_Ptr is access all Object'Class;

Avoid pointers, where possible.

>  procedure Draw(O: Object) is abstract;
> 
>  procedure Set_Text(O: in out Object; Text: String);
>  function Get_Text(O: Object) return String;
> 
> private
>  type Object is abstract tagged record
>   Text: String(1..50);

Consider bounded and unbounded strings here. Note also that if in the
future you will need initialization/finalization, then Object should better
be a descendant of Ada.Finalization.Controlled:

type Object is abstract
   new Ada.Finalization.Controlled with record

Further, if public view of Object remains just tagged, while in the full
view it is derived from Ada.Finalization.Controlled, then in effect it will
be practically impossible to derive from Object in non-children packages.
So, to expose or not Ada.Finalization.Controlled as the base is an
important decision.

>  end record;
> end Objects;

[snip]
 
> -- package Circles:
> with Objects;
> use Objects;
> 
> package Circles is

Probably it should be a child package of Objects, especially if it needs to
look into Object's privates.

>  type Circle is new Object with private;
> 
>  procedure Draw(C: Circle);
> 
>  package Constructor is
>   function Create(Text: String; Radius: Integer) return Circle;
>  end Constructor ;

You do not need a nested package here.

>  private
>   type Circle is new Object with record
>    Radius: Integer;
>   end record;
> end Circles;

[snip] 

> -- main-procedure:
> with Ada.Text_IO;
> with Objects;
> with Circles;
> 
> procedure Main is
>   procedure Call_Dynamic(Object_Ptr: Objects.Object_Ptr) is
>  begin
>     Objects.Draw(Object_Ptr.all);
>  end Call_Dynamic;
>  C2: Circles.Circle;
> begin
>   C2 := Circles.Constructor.Create("Circle1",50);
>  Call_Dynamic(new Circles.Circle'(C2));

This is a memory leak. You allocate an object, but never destroy it. Avoid
pointers! (:-))

> end Main;
> 
>  My question is now, why with Call_Dynamic I call the Draw-procedure in the 
> package Circles, although in the body of Call_Dynamic I directly call the 
> Method in the Objects Package?

You call a dispatching procedure. When its argument is class-wide, which is
the case, because Object_Ptr is a pointer to Object'Class, then the target
is selected according to the actual type tag, which is in your case Circle. 

> Surely it is syntactly correct, cause there 
> is an abstract mehtod Draw in the Objects-Package, but I don't understand 
> why such work with classes in different packages. I tested the same, when 
> all classes are in the same package and surely it worked too, and for me and 
> the understanding of dynamic-dispatching this is clear. How does this 
> internally work with the different-package approach as described above in 
> the source-code?

You have used a qualified expression Circles.Circle'(C2) in new, which
allocates a new object of Circle and initializes it with the value of C2.
Then a pointer to this new object is taken and "converted" to a class-wide
pointer Object_Ptr. The result is passed to Call_Dynamic. Where it is
dereferenced to Object'Class, on which dispatching Draw is called. The
dispatching call gets the tag (->Circle), looks into the dispatching table
of Draw and finds there Draw for Circle (an override of Object.Draw). That
is called.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



  parent reply	other threads:[~2004-10-04  8:02 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-10-02 15:39 Dynamich Dispatching Rick Santa-Cruz
2004-10-03 17:11 ` Martin Krischik
2004-10-03 22:59   ` Brian May
2004-10-04  8:22     ` Martin Krischik
2004-10-03 18:56 ` Ludovic Brenta
2004-10-04  4:45   ` Jeffrey Carter
2004-10-04 21:01     ` Ludovic Brenta
2004-10-05  0:32       ` Jeffrey Carter
2004-10-04  8:02 ` Dmitry A. Kazakov [this message]
2004-10-04 11:02   ` Brian May
2004-10-04 12:50     ` Dmitry A. Kazakov
2004-10-15 18:27       ` Matthew Heaney
2004-10-16 19:25         ` 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