这是我之前发表的帖子的后续内容:
Ada: Understanding private types and understanding packaging
Rectangular
类型的实现是使用一个实现进行的,即Rectangular_Method_1
,此实现需要规范文件和正文文件。
如果我们想让用户可以使用其他实施Rectangular_Method_2
,那么主文件rectangular_Form.ads
可以更改为
-- with Rectangular_Method_1;
-- package Rectangular_Form renames Rectangular_Method_1;
with Rectangular_Method_2;
package Rectangular_Form renames Rectangular_Method_2;
问题
这是否是软件工程中正确的方式,允许另一个实现,因为测试文件test_rectangular_form.adb
对于不同的实现保持不变?
如果我们创建第二个实现Rectangular_Method_2
,除了这个新实现的强制新主体之外,还需要创建一个单独的规范文件吗?但是,有必要在新实现中为Vector_Basis_r
,Set_Horz
,Get_Horz
等提供相同的过程/函数,以便我们可以在test_rectangular_form.adb
中调用它们。
...谢谢
答案 0 :(得分:4)
如果使用GNAT,则可以将GPR文件用于项目。在那里,您可以更改特定包的文件名,例如:
for Specification (Rectangular_Form) use "Rectangular_Method_1.ads";
for Implementation (Rectangular_Form) use "Rectangular_Method_1.adb";
您甚至可以根据环境变量进行设置。
如果您的规范文件看起来都相同,则可以使用Rectangular_Form.ads
并仅使用上面的“实施”行。
示例GPR文件可能如下所示:
project Example is
type Methods is ("normal", "something_else");
Method : Methods := external ("METHOD", "normal");
package Naming is
case Method is
when "normal" =>
for Implementation ("Example") use "example_normal.adb";
when "something_else" =>
for Implementation ("Example") use "example_something.adb";
end case;
end Naming;
end Example;
然后,您可以使用gnatmake -P example.gpr
根据您的METHOD
变量进行编译,或使用g -XMETHOD=...
参数进行编译,或者只使用提供的默认值。
example_*.adb
应该包含包Example
的正文,而不是Example_Normal
等。
答案 1 :(得分:3)
另一种方法是使用标记类型。
package Rectangular is
type Instance is abstract tagged private;
procedure Vector_Basis_r (A : in Long_Float; D : out Instance);
procedure Set_Horz (R : in out Instance; H : Long_Float);
function Get_Horz (R : Instance) return Long_Float;
private
type instance is tagged null record;
end Rectangular;
with Rectangular;
package Rectangular_Method_1 is
type Instance is new Rectangular.Instance with private;
...
private
type Instance is new Rectangular.Instance with
record
Horz, Vert: Long_Float;
end record;
end Rectangular_Method_1;
(Rectangular_Method_2的类似实现)。
然后我相信你可以编写以这种方式使用它的代码:
with Rectangular_Method_1;
with Rectangular_Method_2;
...
-- My_Rectangle : Rectangular_Method_1.Instance;
My_Rectangle : Rectangular_Method_2.Instance;
My_Rectangle.Set_Horiz(Whatever_Value);
...
换句话说,当你在两者之间切换时,你必须改变的只是类型名称。您的客户甚至可以通过在顶部使用单个子类型来消除这些更改。
subtype Rectangle_Instance is Rectangular_Method_2.Instance;
这也使你能够将公共代码/字段移动到基类(包)中,我认为这是你所追求的。