阿达:包装概念

时间:2012-05-02 05:59:09

标签: packaging ada

这是我之前发表的帖子的后续内容:

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;

问题

  1. 这是否是软件工程中正确的方式,允许另一个实现,因为测试文件test_rectangular_form.adb对于不同的实现保持不变?

  2. 如果我们创建第二个实现Rectangular_Method_2,除了这个新实现的强制新主体之外,还需要创建一个单独的规范文件吗?但是,有必要在新实现中为Vector_Basis_rSet_HorzGet_Horz等提供相同的过程/函数,以便我们可以在test_rectangular_form.adb中调用它们。

  3. ...谢谢

2 个答案:

答案 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;

这也使你能够将公共代码/字段移动到基类(包)中,我认为这是你所追求的。