hasan@emx.utexas.edu (David A. Hasan) (02/16/91)
I am having some trouble building generic components in layers. My motivation is to contruct layers as *independent* generic packages by WITHing low layers into higher layers and then adding additional features and "reexporting" some of the old features. I would certainly appreciate any insight you expreienced Ada folks can give me. My question is best asked in the context of an example. Suppose I have the following package which exports a primitive ADT and some fundamental operations on the ADT: GENERIC TYPE item IS PRIVATE; TYPE coord IS (<>); PACKAGE grid IS TYPE adt IS PRIVATE; FUNCTION fetch( from_adt : IN adt; at_y, at_x : IN coord ) RETURN item; PROCEDURE store( the_item : IN item; in_adt : IN OUT adt; at_y, at_x : IN coord ); PRIVATE TYPE adt IS ...whatever...; END grid; "grid.adt" could be used for a number of things, but suppose I want to build a numerical matrix layer on top. Here's my attempt: WITH grid; GENERIC TYPE scalar IS PRIVATE; -- WITH "+", "-" etc... TYPE index IS (<>); PACKAGE matrix IS TYPE adt IS PRIVATE; FUNCTION fetch( from_adt : IN adt; at_row, at_col : IN index ) RETURN scalar; PROCEDURE store( in_adt : IN OUT adt; at_row, at_col : IN index ); FUNCTION invert( the_matrix : IN adt ) RETURN adt; -- etc... PRIVATE PACKAGE low_level IS NEW grid(scalar,index); TYPE adt IS NEW low_level.adt; -- the derived type comes complete with of low_level -- subprograms "fetch" and "store" END matrix; How can one implement "matrix.fetch" and "matrix.store" so that they are the *same* as the derived subprograms fetch and store visible at the end of the PRIVATE part of the package (i.e., how do I reexport them)? For that matter, how can they be implemented to *call* the derived subprograms? Should I perhaps use a SUBTYPE instead of a derived type? ---------------------------------------------------------------- : david a hasan -- Univ. of Texas Ctr. for Space Research : -- hasan@emx.cc.utexas.edu
madmats@elcgl.epfl.ch (02/16/91)
In article <44213@ut-emx.uucp>, hasan@emx.utexas.edu (David A. Hasan) writes: > My question is best asked in the context of an example. Suppose > I have the following package which exports a primitive > ADT and some fundamental operations on the ADT: > > GENERIC > TYPE item IS PRIVATE; > TYPE coord IS (<>); > PACKAGE grid IS > TYPE adt IS PRIVATE; > FUNCTION fetch( from_adt : IN adt; > at_y, at_x : IN coord ) RETURN item; > PROCEDURE store( the_item : IN item; > in_adt : IN OUT adt; > at_y, at_x : IN coord ); > PRIVATE > TYPE adt IS ...whatever...; > END grid; > > "grid.adt" could be used for a number of things, but suppose I want > to build a numerical matrix layer on top. Here's my attempt: > > WITH grid; > GENERIC > TYPE scalar IS PRIVATE; > -- WITH "+", "-" etc... > TYPE index IS (<>); > PACKAGE matrix IS > TYPE adt IS PRIVATE; > FUNCTION fetch( from_adt : IN adt; *** > at_row, at_col : IN index ) RETURN scalar; > PROCEDURE store( in_adt : IN OUT adt; > at_row, at_col : IN index ); -- I guess you meant: *** PROCEDURE store( the_item : in Scalar; *** in_adt : IN OUT adt; at_row, at_col : IN index ); > FUNCTION invert( the_matrix : IN adt ) RETURN adt; > -- etc... > PRIVATE > PACKAGE low_level IS NEW grid(scalar,index); > TYPE adt IS NEW low_level.adt; > -- the derived type comes complete with of low_level > -- subprograms "fetch" and "store" No, it does not because the derived subprograms fetch and sotre are hidden by the ones declared above (see *** marks), because they have the same parameter and result type profile. If you want to call the original subprograms, you have to use type conversions in order to call the subprograms that are declared in the package instance low_level (see below). > END matrix; > > How can one implement "matrix.fetch" and "matrix.store" so that > they are the *same* as the derived subprograms fetch and store visible at the > end of the PRIVATE part of the package (i.e., how do I reexport them)? > For that matter, how can they be implemented to *call* the derived subprograms? package body Matrix is FUNCTION fetch( from_adt : IN adt; at_row, at_col : IN index ) RETURN scalar is begin return Low_Level.Fetch(From_ADT => Low_Level.ADT(From_ADT), -- type conversion At_X => At_Row, At_Y => At_Col); end fetch; PROCEDURE store( the_item : in Scalar; in_adt : IN OUT adt; at_row, at_col : IN index ) is begin Low_Level.Store(The_Item, In_ADT => Low_Level.ADT(In_ADT), At_X => At_Row, At_Y => At_Col); end store; end Matrix; I think all this is awful because if you reuse a lower level ADT for implementing another one, operations that you redefine with the same name are not written in the same way as the ones that are renamed. The problem even becomes worse when the ADTs export generics (iterators for example). At this point, please let me know if you still think Ada does not need a *real* mechanism for inheritance. > > Should I perhaps use a SUBTYPE instead of a derived type? No you shouldn't because you can't: full declarations of private types must be new types, distinct from all others; in particular, they can't be subtypes. Mats Weber
jls@yoda.Rational.COM (Jim Showalter) (02/18/91)
I submitted an Ada 9x on this, since I believe that at the point of derivation you should now get matrix's fetch and store for FREE (this is how it works in an inheritance language like C++) unless you want to specifically override the inherited defaults. Until such time as this is changed, what you do now is write stupid little "skins" that basically just coerce the types from derived to base and/or from base to derived, and call the base type's operations. For example, here is matrix.fetch: function fetch (from_adt : in adt; at_row, at_col : in index) return scalar is begin return low_level.fetch (from_adt => low_level.adt (from_adt), ....); end fetch; Barring this little annoyance, I think a derived type is better than a subtype in this example. -- ***** DISCLAIMER: The opinions expressed herein are my own. Duh. Like you'd ever be able to find a company (or, for that matter, very many people) with opinions like mine. -- "When I want your opinion, I'll beat it out of you."