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;
...一切顺利!
Ada 具有 可见性 的概念,其中有许多规则定义了事物何时、何地以及如何可见。理解可见性是理解 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
的命名空间并不是抽象。
我有一个形式为
的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;
...一切顺利!
Ada 具有 可见性 的概念,其中有许多规则定义了事物何时、何地以及如何可见。理解可见性是理解 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
的命名空间并不是抽象。