Ada:重新导出枚举类型值

Ada: Re-exporting enum type values

我有一个形式为

的ada包
package C is
   type Test is (Test_1, Test_2, Test_3);   
end C;

和另一个形式为

的包
with C;
package B is
   subtype Test is C.Test;
end B;

还有一个

with B;
package A is
   subtype Test is B.Test;   
   Item: Test := Test_1;
end A;

天真地,我希望 B 中定义的子类型(后来由 A 子类型化)能够访问原始类型的成员。但是,经过检查,C的成员甚至在B的范围内都不可见。这可以通过添加use c;来解决,这似乎在某种程度上是一种找到解决方案,但是要在A中使用它,你会必须向每个传递依赖于 C 的包添加 with c; use c;。这可能会导致混淆,因为它不会隐式地明显表明您应该使用 C。

我希望能够“重新导出”这些类型,以便我可以更好地抽象我的程序层。

如果你把包A改成

with B;
package A is
   subtype Test is B.Test;
   use all type Test;
   Item: Test := Test_1;
end A;

代码编译。不确定这是否有帮助。

这是 Ada 2012 的功能;参见 ARM 8.4(8) 和 (8.1)。 use all type 使类型的原始操作可见(包括枚举文字)。

with B;
package A is
   type Test is new B.Test;   
   Item: Test := Test_1;
end A;

...一切顺利!

A​​da 具有 可见性 的概念,其中有许多规则定义了事物何时、何地以及如何可见。理解可见性是理解 Ada 的关键。关于可见性的最佳讨论之一是 Ada Distilled。您遇到的是可见性规则的结果。这比枚举文字更进一步:

package Pack is
   type Int is range -(2 ** 15) + 1 .. 2 ** 15 - 1;
end Pack;

with Pack;
procedure Proc is
   subtype Int is Pack.Int;
   -- None of the operators of Int ("+", "*", ...) are directly visible here
begin
   null;
end Proc;

包规范中的声明仅通过使用点符号在包外可见,除非您明确地使它们在其他地方直接可见。 use 子句是使它们可见的一种方式;其他是 renames 并且对于枚举文字,声明使用点分符号初始化的类型的常量。

如果你真的想重新导出值,你可以这样做:

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;

遗憾的是,您不能使用命名数字,因为枚举不是数字类型。您可以将这些函数改为普通常量,但从概念上讲,这将在详细说明时执行代码(编译器可能会将其优化掉,但您不能再使用 pragma Preelaborate)。

这允许您使用 B.Test_1 等访问 A 中的文字。这也是一个适当的抽象,因为 A 将不依赖于 [=15= 中定义的文字](您可以重命名 C 中的文字而不影响 A,您确实需要更新 B 以将新名称映射到原始名称)。

简单地将文字名称导入 A 的命名空间并不是抽象。