3

这是我之前的帖子的后续:

Ada:理解私有类型和理解封装

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_r然而,需要在新实现中为、等提供相同的过程/函数Set_HorzGet_Horz以便我们可以在test_rectangular_form.adb.

谢谢...

4

2 回答 2

4

如果您使用 GNAT,则可以为项目使用 GPR 文件。在那里您可以更改特定包的文件名,例如:

for Specification (Rectangular_Form) use "Rectangular_Method_1.ads";
for Implementation (Rectangular_Form) use "Rectangular_Method_1.adb";

您甚至可以根据环境变量进行设置。

如果你的规范文件看起来都一样,你可以使用 aRectangular_Form.ads并且只使用上面的 Implementation 行。

示例 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变量来编译它,或者使用-XMETHOD=...gnatmake 的参数或者只使用提供的默认值。

example_*.adb应该都包含包的主体,Example而不是Example_Normal等等。

于 2012-05-02T07:55:50.997 回答
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;

这也将使您能够将通用代码/字段向上移动到基类(包)中,我认为这就是您所追求的。

于 2012-05-02T13:18:04.450 回答