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
next prev parent 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