I have an ada package in the form of
package C is
type Test is (Test_1, Test_2, Test_3);
end C;
and another package in the form of
with C;
package B is
subtype Test is C.Test;
end B;
and yet another in the form of
with B;
package A is
subtype Test is B.Test;
Item: Test := Test_1;
end A;
Naively, I would expect that a subtype defined in B, which is later subtyped by A, would be able to access members of the original type. However, upon inspection, the members of C are not even visible in the scope of B. This can be fixed by adding use c;, this seems like a find solution to a degree, however to use it in A, you would have to add with c; use c; to every package that transitively depends on C. This could lead to confusion as it wouldn't be implicitly obvious that you should be using C.
I would like to be able to "rexport" these types, so that I can abstract layers of my program better.
If you change package A to
with B;
package A is
subtype Test is B.Test;
use all type Test;
Item: Test := Test_1;
end A;
the code compiles. Not sure whether this will help.
This is an Ada 2012 feature; see ARM 8.4(8) and (8.1). use all type makes the primitive operations of the type visible (which includes enumeration literals).
If you really want to re-export the values, you can do this:
with C;
package B is
subtype Test is C.Test;
function Test_1 return Test is (C.Test_1);
function Test_2 return Test is (C.Test_2);
function Test_3 return Test is (C.Test_3);
end B;
Unfortunately, you can't use named numbers since enumerations are not numeric types. You can make these functions normal constants instead, but conceptually, this would execute code at elaboration time (the compiler will probably optimize it away, but you can't use pragma Preelaborate anymore).
This allows you to access the literals in A using B.Test_1 etc. This is also a proper abstraction as A will not depend on the literals defined in C anymore (you can rename the literals in C without affecting A, you do need to update B though to map the new names to the original ones).
Simply importing the literal names into the namespace of A is not an abstraction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With