comp.lang.ada
 help / color / mirror / Atom feed
From: "John G. Volan" <johnvolan@sprintmail.com>
Subject: Re: Syntax for tagged record types (was Re: Not intended for use in medical,)
Date: 1997/05/23
Date: 1997-05-23T00:00:00+00:00	[thread overview]
Message-ID: <33867D87.21BA@sprintmail.com> (raw)
In-Reply-To: JSA.97May23142418@alexandria


I (John Volan) wrote:

>Another issue with discriminants as constructor parameters is that there
>is no provision for having multiple overloaded constructors with
>different sets of parameters.

Jon S Anthony replied:
> 
> This is a non issue for anything other than a limited type.  You can
> name your constructors whatever you want, they can take any number of
> parameters and there can be any number of them.

My reply:

Just so folks won't be confused, what Jon's referring to here are
ordinary Ada functions that happen to return a value of a given type,
e.g.

  type Some_Value_Type is ... -- something non-limited

  function Make_Some_Value (... from one set of parameters ...)
    return Some_Value_Type;

  function Make_Some_Value (... from another set of parameters ...)
    return Some_Value_Type;

  ... etc.

This then allows a user to construct a value of the given type during an
object declaration, in the initialization part:

   Some_Value : Some_Value_Type := Make_Some_Value (...);

The designer of the abstraction can even force users to always call one
of these constructor functions, by giving the type an unknown
discriminant part, thereby making it an "indefinite" type:

   type Some_Value_Type (<>) is ... private; -- something non-limited

This doesn't mean the actual completion of this type has to have a
discriminant, but it does make uninitialized variables illegal:

   Some_Value : Some_Value_Type; -- compiler error! indefinite type!

This restriction is appropriate if the abstraction just doesn't include
any notion of a "default" constructor.

> For limited types, the only way around this is to hide them behind
> access types for them.  

Right, when you deal with true object-oriented abstractions (as opposed
to value-oriented abstract data types), you inevitably have to invoke
reference semantics and the identity-vs-state issue.

Here's a pattern I like to use for object-oriented types:

   type Some_Object_Type (<>) is tagged limited private;
   type Some_Object_Access_Type is access all Some_Object_Type'Class;

   function Make_Some_Object (... from one set of parameters ...)
     return Some_Object_Access_Type;

   function Make_Some_Object (... from another set of parameters ...)
     return Some_Object_Access_Type;
   ...

   procedure Primitive_Operation
     (Some_Object : access Some_Object_Type;
      ... parameters ... );

   ... etc.

Note that:

(1) Some_Object_Type is limited, so assignment can't be used to casually
copy the state of one object into another. (Althought the abstraction
designer could certainly choose to provide subprograms that do deep
copies, but calling these subprograms wouldn't be "casual".)

(2) On the other hand, Some_Object_Access_Type is (of course) _not_
limited, so assignments can be used to copy object _identities_ (access
values, "references" to objects) as much as you please.

(3) Some_Object_Type has an unknown discriminant part, so a direct
declaration for an object of this type is illegal:

  Some_Object : Some_Object_Type; -- compiler error! indefinite type!

And the users can't get around this by trying to initialize the object
to something -- because it's a limited type, so assignment is illegal. 
Instead, the users are forced to go through one of the constructors
defined for the abstraction:

  Some_Object : Some_Object_Access_Type := Make_Some_Object (...);

But note that what we have here is only an _access_ to some object.  The
abstraction has complete control over where that object actually is. 
(The object will commonly be allocated on the heap, but that's not
necessarily the only possibility.)

(4) Since the constructor functions all return values of the access type
and not the object type itself, these functions are _not_ primitive
subprograms for the object type, so they will _not_ be inherited by
derived types ("subclasses").  This is actually a good thing: It has
frequently been argued that constructors should not be inheritable. (In
fact, C++'s constructors aren't.)

(5) If a subclass can't just inherit a constructor, and the parent class
doesn't include a default constructor, then the only way the subclass
can properly implement a constructor of its own is if it somehow has
access to the implementation details of its parent class. That pretty
much forces you to put your subclasses into child packages.  Giving the
base type an unknown discriminant also forces this, because it's illegal
to derive a new type unless you can provide a constraint for the
discriminant (or "see" that there really isn't one).

To make it a little easier to implement child constructors, I like to
use a pattern where, for every visible constructor _function_ which I
provide to clients, I accompany it with a private constructor
_procedure_, which the constructor function calls, and which child
constructors can also call:

  package Base_Class is
    type Base_Type (<>) is tagged limited private;
    type Base_Access_Type is access all Base_Type'Class;

    function Make_Base (...some base set of parameters...)
      return Base_Access_Type;
    ...
  private
    type Base_Type is tagged limited record ...

    procedure Make_Base
      (Base : access Base_Type'Class;
       ...same base set of parameters...);
    ...
  end Base_Class;

A Make_... function would typically allocate a new object from
somewhere, then call the corresponding hidden Make_... procedure to
initialize the object, then return the new access value.

Note that I write my Make_... procedures as _classwide_ subprograms, so
they aren't inheritable primitives any more than my Make_... functions. 

A subclass package would look something like this:

  package Base_Class.Derived_Class is
    type Derived_Type (<>) is new Base_Type with private;
    type Derived_Access_Type is access all Derived_Type'Class;

    function Make_Derived (...base parameters...plus others maybe...)
      return Derived_Access_Type;
    ...
  private
    type Derived_Type is new Base_Type with record ...

    procedure Make_Derived
      (Derived : access Derived_Type'Class;
       ...base parameters...plus others maybe...);
    ...
  end Base_Class.Derived_Class;

The derived Make_... procedure for a subclass like this would typically
call the base Make_... procedure for its parent class, and then would do
whatever additionally initializations are needed for its type
extension.  Since the derived class is in a child package, it can "see"
the hidden base Make_... procedure.  And since the base-type object
initialized by the base Make_... procedure is a classwide parameter, the
derived Make_... procedure can pass its derived-type object into this
parameter.

> Then things again work just fine - except for
> storage management issues.  Hence, the need for GC.  Limited types are
> really extremely useful.  Unfortunately, much of this is lost without
> GC support.

Agreed.

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name => "John G. Volan",  Home_Email => "johnvolan@sprintmail.com",
   Slogan => "Ada95: The World's *FIRST* International-Standard OOPL",
   Disclaimer => "These opinions were never defined, so using them " & 
     "would be erroneous...or is that just nondeterministic now? :-) ");
------------------------------------------------------------------------




  reply	other threads:[~1997-05-23  0:00 UTC|newest]

Thread overview: 120+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1997-04-23  0:00 Not intended for use in medical, Robert C. Leif, Ph.D.
1997-04-24  0:00 ` J. Florio
1997-04-25  0:00 ` Ken Garlington
1997-04-25  0:00 ` Kevin Cline
1997-04-25  0:00   ` Robert Dewar
1997-04-28  0:00 ` John Apa
1997-04-28  0:00   ` John M. Mills
1997-04-30  0:00     ` Larry Kilgallen
1997-05-02  0:00       ` Nick Roberts
1997-04-28  0:00   ` Robert Dewar
1997-04-29  0:00     ` Kaz Kylheku
1997-04-30  0:00       ` John Apa
     [not found]       ` <3367CE1E.5ED1@die_spammer.dasd.honeywell.com>
1997-05-01  0:00         ` Kaz Kylheku
1997-05-03  0:00       ` Simon Wright
1997-05-04  0:00         ` Robert Dewar
1997-05-04  0:00         ` Kaz Kylheku
1997-05-04  0:00           ` Robert Dewar
1997-05-04  0:00             ` Richard Kenner
1997-05-05  0:00             ` Kaz Kylheku
1997-05-06  0:00               ` Kaz Kylheku
1997-05-06  0:00                 ` Robert A Duff
1997-05-07  0:00                   ` Robert Dewar
1997-05-08  0:00                     ` Robert A Duff
1997-05-09  0:00                       ` Robert I. Eachus
1997-05-11  0:00                         ` Robert Dewar
1997-05-11  0:00                           ` Matthew Heaney
1997-05-12  0:00                             ` Robert Dewar
1997-05-12  0:00                               ` Matthew Heaney
1997-05-13  0:00                                 ` Jon S Anthony
1997-05-13  0:00                                   ` Matthew Heaney
1997-05-14  0:00                                     ` Robert Dewar
1997-05-14  0:00                                     ` Robert Dewar
1997-05-14  0:00                                 ` Robert Dewar
1997-05-15  0:00                                   ` W. Wesley Groleau (Wes)
1997-05-14  0:00                                 ` Nick Roberts
1997-05-14  0:00                                 ` Robert Dewar
1997-05-12  0:00                           ` Robert I. Eachus
1997-05-13  0:00                             ` Robert Dewar
1997-05-14  0:00                               ` Nick Roberts
1997-05-14  0:00                                 ` Robert Dewar
     [not found]                                   ` <01bc6182$30e3a7c0$LocalHost@xhv46.dial.pipex.com>
1997-05-16  0:00                                     ` Robert Dewar
1997-05-16  0:00                                     ` Robert A Duff
1997-05-16  0:00                                       ` Robert I. Eachus
1997-05-18  0:00                                         ` Nick Roberts
1997-05-18  0:00                                           ` Matthew Heaney
1997-05-19  0:00                                             ` Robert I. Eachus
1997-05-19  0:00                                               ` Matthew Heaney
1997-05-20  0:00                                                 ` Nick Roberts
1997-05-20  0:00                                                   ` Matthew Heaney
1997-05-21  0:00                                                     ` Dale Stanbrough
1997-05-19  0:00                                             ` Robert A Duff
1997-05-08  0:00                     ` Kaz Kylheku
1997-05-08  0:00                       ` Robert Dewar
1997-05-09  0:00                         ` Kaz Kylheku
1997-05-12  0:00                       ` W. Wesley Groleau (Wes)
1997-05-12  0:00                         ` John G. Volan
1997-05-14  0:00                       ` Nick Roberts
1997-05-14  0:00                         ` Robert Dewar
1997-05-14  0:00                           ` Jeff Carter
     [not found]                             ` <dewar.863632434@merv>
1997-05-15  0:00                               ` Kaz Kylheku
1997-05-18  0:00                                 ` Robert Dewar
1997-05-15  0:00                         ` Kaz Kylheku
1997-05-08  0:00                     ` John G. Volan
1997-05-10  0:00                       ` Robert Dewar
1997-05-10  0:00                         ` John G. Volan
1997-05-11  0:00                           ` Robert Dewar
1997-05-11  0:00                             ` John G. Volan
1997-05-11  0:00                               ` Robert A Duff
1997-05-12  0:00                                 ` John G. Volan
1997-05-12  0:00                                 ` Robert Dewar
1997-05-11  0:00                             ` John G. Volan
1997-05-11  0:00                               ` Robert Dewar
1997-05-12  0:00                             ` John G. Volan
1997-05-12  0:00                               ` Robert Dewar
1997-05-17  0:00                               ` Robert I. Eachus
     [not found]                                 ` <dewar.863877808@merv>
1997-05-17  0:00                                   ` Robert Dewar
1997-05-17  0:00                                     ` Jon S Anthony
1997-05-21  0:00                                       ` Syntax for tagged record types (was Re: Not intended for use in medical,) Ben Brosgol
1997-05-20  0:00                                         ` Matthew Heaney
1997-05-21  0:00                                           ` Syntax for tagged record types and class types Mats Weber
1997-05-21  0:00                                             ` Matthew Heaney
1997-05-22  0:00                                               ` Mats Weber
1997-05-27  0:00                                               ` Tucker Taft
1997-05-30  0:00                                                 ` Mats.Weber
1997-05-22  0:00                                             ` Samuel A. Mize
1997-05-22  0:00                                               ` Samuel A. Mize
1997-05-23  0:00                                               ` Mats Weber
1997-05-21  0:00                                           ` Syntax for tagged record types (was Re: Not intended for use in medical,) Jon S Anthony
1997-05-21  0:00                                             ` Matthew Heaney
1997-05-22  0:00                                               ` Robert I. Eachus
1997-05-25  0:00                                                 ` Matthew Heaney
1997-05-28  0:00                                                   ` Robert I. Eachus
1997-05-23  0:00                                               ` Jon S Anthony
1997-05-23  0:00                                                 ` Matthew Heaney
1997-05-25  0:00                                                   ` Jon S Anthony
1997-05-28  0:00                                                   ` Syntax for tagged record types (was Re David Kristola
1997-05-23  0:00                                                 ` Syntax for tagged record types (was Re: Not intended for use in medical,) Simon Wright
     [not found]                                         ` <mheaney-ya023680002005972314260001@news.ni.net <mheaney-ya023680002105972302430001@news.ni.net>
1997-05-22  0:00                                           ` Robert A Duff
1997-05-22  0:00                                             ` John G. Volan
1997-05-23  0:00                                               ` Matthew Heaney
1997-05-23  0:00                                                 ` Jon S Anthony
1997-05-23  0:00                                                   ` John G. Volan [this message]
1997-05-24  0:00                                                     ` Robert A Duff
1997-05-24  0:00                                                       ` Matthew Heaney
1997-05-28  0:00                                                         ` Robert I. Eachus
1997-05-25  0:00                                                     ` Jon S Anthony
1997-05-23  0:00                                                   ` Matthew Heaney
1997-05-25  0:00                                                     ` Jon S Anthony
1997-05-25  0:00                                                     ` Robert Dewar
1997-05-27  0:00                                                     ` Ray Blaak
1997-05-23  0:00                                               ` Jon S Anthony
1997-05-12  0:00                             ` Not intended for use in medical, John G. Volan
1997-05-12  0:00                         ` Language Design Mistakes (was "not intended...") W. Wesley Groleau (Wes)
1997-05-13  0:00                           ` Robert Dewar
1997-05-13  0:00                             ` W. Wesley Groleau (Wes)
1997-05-13  0:00                             ` Robert A Duff
1997-05-14  0:00                               ` Robert Dewar
1997-05-07  0:00                   ` Not intended for use in medical, Kaz Kylheku
1997-05-08  0:00                     ` Robert A Duff
1997-05-04  0:00         ` Richard Kenner
replies disabled

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