comp.lang.ada
 help / color / mirror / Atom feed
From: Richard Irvine <irv@eurocontrol.fr>
Subject: Re: Cumbersome Polymorphism
Date: 1997/01/28
Date: 1997-01-28T00:00:00+00:00	[thread overview]
Message-ID: <32EE3E5C.4D4C@eurocontrol.fr> (raw)
In-Reply-To: 32ECF2A3.6371@watson.ibm.com


As usual, many thanks for your reply.

My basic point is that in order to make  simple use of polymorphism
the user of tagged types has to allocate and deallocate storage.
If, due to programming errors, deallocation is not done or not done
in the right place, the consequence can be memory leaks or dangling
references. (One of Ada's fortes is its static type checking, which
commends it for use in systems which must be highly reliable. The static
type checking is an important contribution to reliability, but I can
undo all the benefit to be gained from this, if I forget to deallocate
something or deallocate it in the wrong place). Also, by requiring the
routine use of access types, one might end up going down the slippery
road of passing access types around a program without being sure 
where or when they should be deallocated.
 
It would be good if the memory management associated with a tagged type
could be taken care of in the (single) package in which the type is 
defined, not in the (multiple) places where it is used, if not, every
polymorphic use of the type is an invitation to make deallocation
errors.
If I have a variable which holds a shape of some kind, I want to be able
to assign a triangle or a square to it without having to think about
allocation or deallocation, and without having the opportunity to get it
wrong.
   
In his posting, Robert Dewar gives the example of Ada.Unbounded.Strings.
The user of Unbounded_String does not have to allocate or deallocate the
String which Unbounded_String actually points to. I can assign one
Unbounded_String to another, oblivious to the fact that storage is
allocated and deallocated in the process. 
This certainly shows how to hide allocation and deallocation which gives
me an idea: why not put the allocation and deallocation in a generic 
controlled wrapper, e.g.


with Ada.Finalization;
use  Ada.Finalization; 

generic

   type User_Type (<>) is private;

package Controlled_Wrapper_P is

   type Controlled_Wrapper is private;

   function  Wrap
           ( The_User_Type          : User_Type          )
   return                             Controlled_Wrapper;

   function  Unwrap
           ( The_Controlled_Wrapper : Controlled_Wrapper )
   return                             User_Type;
 
private

   type Access_User_Type is access User_Type;

   type Controlled_Wrapper
      is new Controlled
      with record
         Reference : Access_User_Type;
      end record;

   procedure Initialize ( Object : in out Controlled_Wrapper );
   procedure Adjust     ( Object : in out Controlled_Wrapper );
   procedure Finalize   ( Object : in out Controlled_Wrapper );

end;


Renaming the types given before to something more homely:


package Shapes is

  type Shape is abstract tagged null record;

  procedure Do_Something_To( The_Shape    : Shape    )
  is abstract;

  type Triangle is new Shape with null record;
  procedure Do_Something_To( The_Triangle : Triangle );

  type Square   is new Shape with null record;
  procedure Do_Something_To( The_Square   : Square   );

end;


and instantiating the generic for Shape'Class


with Shapes;
use  Shapes; 
with Controlled_Wrapper_P;

package Shape_Wrapper_P
   is new Controlled_Wrapper_P(User_Type => Shape'Class);


Now I can make use of polymorphism with the allocation and deallocation
done by the controlled wrapper, i.e., 


with Shapes;
use  Shapes;
with Shape_Wrapper_P;
use  Shape_Wrapper_P;

procedure Main_Procedure

is

   The_Triangle : Triangle;
   The_Square   : Square;

   type Shape_Wrapper is new Shape_Wrapper_P.Controlled_Wrapper;

   The_Wrapped_Triangle : Shape_Wrapper := Wrap(The_Triangle);
   The_Wrapped_Square   : Shape_Wrapper := Wrap(The_Square  );

   The_Wrapped_Shape    : Shape_Wrapper;

begin

   The_Wrapped_Shape := The_Wrapped_Triangle;
   Do_Something_To(The_Shape => Unwrap(The_Wrapped_Shape));
   -- calls Do_Something_To for Triangle

   The_Wrapped_Shape := The_Wrapped_Square;
   Do_Something_To(The_Shape => Unwrap(The_Wrapped_Shape));
   -- calls Do_Something_To for Square

end;




      parent reply	other threads:[~1997-01-28  0:00 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1997-01-23  0:00 Cumbersome Polymorphism Richard Irvine
     [not found] ` <5c9put$48t@hetre.wanadoo.fr>
1997-01-25  0:00   ` Robert A Duff
1997-01-25  0:00     ` James O'Connor
1997-01-26  0:00       ` Robert Dewar
1997-01-26  0:00       ` Brian Rogoff
1997-01-25  0:00   ` James O'Connor
1997-01-27  0:00   ` Jon S Anthony
1997-01-29  0:00     ` Robert Dewar
1997-01-27  0:00 ` Norman H. Cohen
1997-01-28  0:00   ` Jon S Anthony
1997-01-28  0:00   ` Dave Gibson
1997-01-28  0:00   ` Richard Irvine [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