comp.lang.ada
 help / color / mirror / Atom feed
* Performing I/O on Private Types in Ada 9X (Was Re: OO Preprocessor for Ada)
@ 1993-08-20 17:49 cis.ohio-state.edu!magnus.acs.ohio-state.edu!math.ohio-state.edu!darwin.s
  0 siblings, 0 replies; 2+ messages in thread
From: cis.ohio-state.edu!magnus.acs.ohio-state.edu!math.ohio-state.edu!darwin.s @ 1993-08-20 17:49 UTC (permalink / raw)


>Obviously you're right, I was just asleep in the front row again.
>
>I guess what this example triggered was painful memories of trying 
>to provide text_io capabilities when you declare a limited private type.
>Does anyone have an elegant example of how to do this with 9X with tagged
>types and text_io generics?
>
>I guess to further define the problem, using this running example,
>how can I provide a text_io print capability of an object of type X.Object?
>(i.e. how do I print An_Object directly?).

Well, by the very nature of An_Object being declared of a private type, you 
can't -- and the fact that this private type happens to be tagged doesn't 
change that.  In other words, an ordinary piece of client code is afforded no 
more visibility into a tagged object's private structure than is realized by a 
non-tagged object.  While an ordinary program unit may indeed extend a tagged 
type with new components, the program unit that derives the new type does not 
gain visibility into the original type's private part simply by doing such a 
type extension.  But fear not, for your "painful memories" may be disposed of 
by an entirely different feature of Ada 9X, that being the _child library 
unit_.

A child library unit is a separately compiled program unit that, among other 
things, can "see" into the private structure of its parent package.  Such a 
construct allows us to effectively add declarations to an existing package 
without requiring modification to the original package itself.  Much as tagged 
types allow us to extend the set of components defined for an existing record 
type, child library units allow us to extend the set of declarations defined 
by an existing package.  

Now although I've used child units to implement inheritance hierarchies, I 
haven't yet applied them to I/O problems.  But for the sake of addressing this 
key problem in Ada 83, I'll give it a shot (Tucker, watch out for me, and jump 
in any time...).

To re-establish context, I'll re-specify the example package used in earlier 
postings:

   package X is -- Represents a class X identified in OOA/OOD
      type Object is tagged limited private; -- Represents a "root class"
      procedure Create (Instance : in out Object);    -- "constructor"
                        A1       : in     Integer);
      procedure Modify (Instance : in out Object;     -- "modifier"
                        A1       : in     Integer;
      function P1 (Instance : Object) return Integer; -- (direct) "selector"
   private
      type Object is tagged
         record
            A1 : Integer;
         end record;
   end X;

(Note that I changed each identifier P1 to A1, suggesting that the components 
of the tagged record represent an object's _Attributes, and that direct 
selector functions can be simply named accordingly.)

Now, consider the following child library unit created from the parent package 
X shown above:

   package X.IO is
      procedure Print_Attributes (Instance : in Object);
         -- the type Object is directly visible from the parent unit X
   end X.IO;
   -----------------------------------------------------
   with Text_IO;
   package body X.IO is
      procedure Print_Attributes (Instance : in Object) is
         -- Could instantiate Text_IO.Integer_IO instead of using 'IMAGE below
      begin
         Text_IO.Put ("The value of A1 is ");
         Text_IO.Put ( Integer'IMAGE(Instance.A1) ); -- A1 directly visible
         -- Could print other attributes if they existed
      end Print_Attributes;
   end X.IO;

Note that the child unit is afforded _direct_ visibility to all of its 
parent's specifications.  This is why the formal parameter for 
Print_Attributes need not reference the type as X.Object.  But to really 
address Ken's questions on I/O, the child's _body_ has direct visibility to 
its parent's _private_ declarations as well.  For those readers familiar with 
C++, child library units provide the "protected" form of visibility control 
defined by classes, which gives derived classes direct visibility into their 
parents' otherwise hidden members.  Note, however, that in C++, the class 
designer must decide which members are to be "protected," whereas in Ada 9X, 
the "subclass" designer makes the decision.

This is, I think, a most significant enhancement to Ada 83's sometimes overly 
restrictive visibility rules regarding packages with private parts.  But maybe 
what's even more notable about using child library units in this way is that 
the original (parent) package X need not ever be concerned with the often 
unstable and non-portable nature of performing I/O in general.  Thus, package 
designers can now readily build software components independently of any I/O 
that might be needed, knowing that such capabilities can be later developed 
and modified totally separately.

For completeness, I'll revise the client code specified earlier, having it 
call upon the I/O child package to do its printing instead of within the 
client itself:

   with X.IO; -- Implicitly with's in X as well
   procedure Some_Client_With_IO_Removed is
      An_Object : X.Object;
   begin
      X.Create (Instance => An_Object, A1 => 7);
      X.Modify (An_Object, A1 => 3);
      X.IO.Print_Attributes (Instance => An_Object);
   end Some_Client_With_IO_Removed;

Note that references to lower-level child units can become quite lengthy.  In 
these cases, proper application of renaming (or the 'use' statement) would be 
in order.  In any event, I think that this new capability of Ada 9X is most 
remarkable, especially for those like Ken Rowe who have been previously 
frustrated with Ada 83's "all-or-nothing" effect of private types.
-- 
Gary J. Cernosek
Fastrak Training Inc.
Houston Office: (713) 280-4768
E-mail: cernosek@source.asset.com

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Performing I/O on Private Types in Ada 9X (Was Re: OO Preprocessor for Ada)
@ 1993-08-23 16:03 cis.ohio-state.edu!pacific.mps.ohio-state.edu!math.ohio-state.edu!howland
  0 siblings, 0 replies; 2+ messages in thread
From: cis.ohio-state.edu!pacific.mps.ohio-state.edu!math.ohio-state.edu!howland @ 1993-08-23 16:03 UTC (permalink / raw)


I like your example, but let me do a more concrete one.

Let's say I want to provide the capabilities of enumeration io for
my private type.  If type Object is not limited private, then
procedure Some_Client_With_Io_Removed can just instantiate enumeration_io:

with X;
with Text_Io;
procedure Some_Client_With_Io_Removed is
package X_Io is new 
	Text_Io.Enumeration_Io(	Enum=>	X.Object,
				Image=>	X.Object'Image,
     				Value=>	X.Object'Value); 
...
end Some_Client_With_Io_Removed;

But since X.Object is (tagged) limited private it is not so straight forward.
Using your example I need to do the following:

with Text_Io;
package X.Io is
	procedure Get(File: in Text_Io.In_File;Item: out Object);
        procedure Get(Item: out Object);
        procedure Put(File: in Text_Io.Out_File; Item: in Object;
                      Width: in Integer := 0;
                      Lower_Case: in Boolean := False);
        procedure Put(Item: in Object;
                      Width: in Integer := 0;
                      Lower_Case: in Boolean := False);
end X.Io;

with Text_Io;
package body X.Io is
	package Object_Io is new 
		Text_Io.Enumeration_Io(	Enum=>	X.Object,
					Image=>	X.Object'Image,
     					Value=>	X.Object'Value); 

	procedure Get(File: in Text_Io.In_File;Item: out Object) is
        	begin
                  Object_Io.Get(File;Item);
                end Get;
        procedure Get(Item: out Object) is
                begin
		  Object_Io.Get(Item);
                end Get;
        procedure Put(File: in Text_Io.Out_File; Item: in Object;
                      Width: in Integer := 0;
                      Lower_Case: in Boolean := False) is
                begin
                  Object_Io.Put(File; Item; Width; Lower_Case);
                end Put;
        procedure Put(Item: in Object;
                      Width: in Integer := 0;
                      Lower_Case: in Boolean := False) is
                begin
                  Object_Io.Put(Item; Width; Lower_Case);
                end Put;
end X.Io;

-------------------------------
What I'd really like to be able to do is

with Text_Io;
package X.Io is new 
	Text_Io.Enumeration_Io(	Enum=>	Object,
				Image=>	Object'Image,
     				Value=>	Object'Value);
end X.Io;

------
(1) Could I have used renames in the long example?

(2) Is the "really like to" example legal in 9X? (my feeling is that
it isn't).

Ken. 

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~1993-08-23 16:03 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1993-08-23 16:03 Performing I/O on Private Types in Ada 9X (Was Re: OO Preprocessor for Ada) cis.ohio-state.edu!pacific.mps.ohio-state.edu!math.ohio-state.edu!howland
  -- strict thread matches above, loose matches on Subject: below --
1993-08-20 17:49 cis.ohio-state.edu!magnus.acs.ohio-state.edu!math.ohio-state.edu!darwin.s

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