comp.lang.ada
 help / color / mirror / Atom feed
* Interface using abstract types
@ 1996-07-04  0:00 Richard Irvine
  0 siblings, 0 replies; only message in thread
From: Richard Irvine @ 1996-07-04  0:00 UTC (permalink / raw)
  Cc: irv


Apologies in advance for the length of this posting.

We are designing a subsystem which might be bound 
into a number of client applications. We wish to 
define the subprograms which the client application
must provide for our purposes. 

e.g. We define

     type Abstract1 is abstract tagged null record;

     procedure anOperation(on : in out Abstract1)
     is abstract;


     type Abstract2 is abstract tagged null record; 
     
     procedure doSomethingWith
	     ( aThing           : in out Abstract2;
	       andSomethingElse : in     Abstract1'Class )
     is abstract;

and the client application provides

     type ClientXConcrete1 is new Abstract1 with ...;
     
     procedure anOperation(on : in out ClientXConcrete1);

 
     type ClientXConcrete2 is new Abstract2 with ...; 
   
     procedure doSomethingWith
  	     ( aThing           : in out ClientXConcrete2;
	       andSomethingElse : in     Abstract1'Class);
	        
The type of the parameter andSomethingElse in the concrete 
version of doSomethingWith must be Abstract1'Class in order to 
conform with the abstract version. 
However, we really only want the client application to
have to provide operations which are valid for its set
of types, rather than for the entire class.
Furthermore, the operations on Abstract1 are those needed by
our subsystem for its purposes. 
To provide an implementation of doSomethingWith the client
may need to use additional operations on
its descendant of Abstract1. However, it cannot do
this and still conform to the abstract doSomethingWith.

So it seems that when defining the abstract doSomethingWith
we should not have had a parameter of type Abstract1'Class.

A possible solution to this problem is as follows:

package abstract1package is

 -- an abstract type to which the client application must conform

   type Abstract1 is abstract tagged null record;

end;

with abstract1package;
use  abstract1package;

package clientx.concrete1package is

 -- a particular client application's implementation of the abstract
type

    type Concrete1 is new Abstract1 with ...; 
	     
end;

-- hide the name of the client whose concrete types we are using
with clientx.concrete1package;
package customisation.concrete1package renames clientx.concrete1package;

with customisation.concrete1package; 
use  customisation.concrete1package;

package abstract2package is

   type Abstract2 is abstract tagged  null record;

-- specify the operation on Abstract2 using a parameter of a 
-- concrete type without knowing which client is providing it   
   procedure doSomethingWith
	   ( aThing           : in out Abstract2;
	     andSomethingElse : in     Concrete1'Class );
	     
end;


-- a client's implementation of Abstract2

with abstract2package; 
use  abstract2package;
with customisation.concrete1package; 
use  customisation.concrete1package;

package clientx.concrete2package is

   type Concrete2 is new Abstract2 with ...;
   
   procedure doSomethingWith
	   ( aThing           : in out Concrete2;
	     andSomethingElse : in     Concrete1'Class );
	     
end;

-- once again hide the name of the client providing the implementation

with clientx.concrete2package;
package customisation.concrete2package renames clientx.concrete2package;


-- finally an example of part of a subsystem

with customisation.concrete1package;
use  customisation.concrete1package;
with customisation.concrete2package;
use  customisation.concrete2package;

procedure framework
        ( aConcrete1 : in     Concrete1;
          aConcrete2 : in out Concrete2 ) is
begin
   doSomethingWith
     (aThing           => aConcrete2, 
      andSomethingElse => aConcrete1);
end;

The advantage of this scheme is that we specify using abstract types
what the client must provide, while the client is free to write
operations which are valid for its set of types. 
Which client's types are being used can be switched in the rename
clauses.

While not altogether ugly this does seem like a rather roundabout
scheme. Have we missed the point, is there a better way of doing
things?




^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~1996-07-04  0:00 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-07-04  0:00 Interface using abstract types Richard Irvine

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