comp.lang.ada
 help / color / mirror / Atom feed
From: Matthew Heaney <matthew_heaney@acm.org>
Subject: Re: Help - Constructors - ASAP.
Date: 1998/08/01
Date: 1998-08-01T00:00:00+00:00	[thread overview]
Message-ID: <m3yat9vfrz.fsf@mheaney.ni.net> (raw)
In-Reply-To: EACHUS.98Jul31173449@spectre.mitre.org

eachus@spectre.mitre.org (Robert I. Eachus) writes:

>    Note that there ARE cases where you do want to have a dispatching
> constructor.   In those cases you really do want to have a constructor
> that is derived, and you (or someone else) will have to do the
> explicit overriding.

Note that there are two kinds of dispatching: dispatch on the return
type, and dispatch on a parameter.

Bob is talking about the first case, dispatching on the return type.  A
common example of this sort of thing is a set type with a constructor
that returns the empty set:

generic
   type Set_Item is private;
   with function "=" (L, R : Set_Item) return Boolean is <>;
package Sets is

   type Root_Set is abstract tagged null record;

   function Empty_Set return Root_Set'Class;

   <other primitive ops>
...
end Sets;


I might use the constructor like this:

procedure Op (Set : in Root_Set'Class) is

   Local : Set'Class := Set;

begin

   <do some stuff>

   Local := Empty_Set;

   <do some more stuff>

end Op;


The function Empty_Set is a constructor that dispatches on the tag of
object Local.  Here is a case where you really want to have a
constructor that returns the specific type.  Each non-abstract type that
derives from Root_Set will have to provide an Empty_Set constructor.

That's an example of the first kind of constructor.  The other kind of
constructor returns a class-wide object, and dispatches on a parameter.
An example of this kind of constructor is a "factory method."

Consider our set type again.  Suppose we have an operation that takes a
class-wide parameter, and we want to iterate over that set.  What we can
do is have the set provide a factory method to construct an iterator
that can be used to iterate over that that kind of set.

Let's add an iterator type to our example:

generic
...
package Sets is

   type Root_Set is abstract tagged null record;

   type Set_Iterator is abstract tagged null record;

   function New_Iterator 
     (Set : access Root_Set) return Set_Iterator'Class;


   function Is_Done
     (Iterator : Set_Iterator) return Boolean is abstract;

   function Get_Item 
     (Iterator : Set_Iterator) return Set_Item is abstract;

   procedure Advance 
     (Iterator : in out Set_Iterator) is abstract;
...
end Sets;


Note that the constructor, New_Iterator, returns a class-wide type.

Let's use our constructor to implement a passive iterator that works for
any type in the set class.  Here's the spec:

generic
   with procedure Process
     (Item : in     Set_Item;
      Done : in out Boolean);
procedure For_Every_Item (Set : access Root_Set'Class);


Note how the Set parameter is class-wide.  Here's the body:

procedure For_Every_Item (Set : access Root_Set'Class) is

   Iterator : Set_Iterator'Class := New_Iterator (Set);

   Done : Boolean := False;

begin

   while not Is_Done (Iterator) loop

      Process (Get_Item (Iterator), Done);

      exit when Done;

      Advance (Iterator);

   end loop;

end For_Every_Item;


The New_Iterator constructor dispatches on the Set parameter.  Each of
the iterator operations (like Get_Item) then dispatches on the tag of
the Iterator object.

There you have it.  Two examples of constructors, one returning a
specific type, the other returning a class-wide type.  Both techniques
are appropriate for different kinds of problems.

Happy constructing!

Matt





  reply	other threads:[~1998-08-01  0:00 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1998-07-23  0:00 Help - Constructors - ASAP Maxim Senin
1998-07-26  0:00 ` Matthew Heaney
1998-07-27  0:00   ` dennison
1998-07-30  0:00     ` Robert I. Eachus
1998-07-30  0:00       ` tedennison
1998-07-31  0:00         ` Matthew Heaney
1998-07-31  0:00         ` Mats Weber
1998-07-31  0:00           ` dennison
1998-08-01  0:00             ` Matthew Heaney
1998-08-01  0:00             ` Robert Dewar
1998-08-01  0:00               ` Matthew Heaney
1998-08-03  0:00             ` Mats Weber
1998-07-31  0:00           ` Robert I. Eachus
1998-08-01  0:00             ` Matthew Heaney [this message]
1998-08-01  0:00       ` Robert Dewar
1998-08-01  0:00         ` Matthew Heaney
1998-08-03  0:00           ` Mats Weber
1998-08-03  0:00             ` Matthew Heaney
1998-08-03  0:00               ` Mats Weber
1998-08-04  0:00                 ` Matthew Heaney
1998-08-04  0:00                   ` Mats Weber
1998-08-05  0:00                     ` Matthew Heaney
1998-08-10  0:00           ` Robert I. Eachus
1998-08-03  0:00         ` tedennison
  -- strict thread matches above, loose matches on Subject: below --
1998-07-15  0:00 Maxim Senin
1998-07-16  0:00 ` Stephen Leake
replies disabled

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