Ada通用包扩展

时间:2017-03-12 10:18:27

标签: generics ada

我有一个通用包Containers.Stacks,看起来大致像

generic
    type Value_Type is private;
package Containers.Stacks with Preelaborate is

    --Node stuff

    type Stack is new Container with private;

    --Other Stack stuff
    --Private stuff
end Containers.Stacks;

所有关于(似乎)工作得很好。我想重用此实现来创建扩展但更窄的目的堆栈。我想出了以下内容:

with Containers.Stacks;

generic
    type Value_Type is range <>;
package Containers.Integer_Stacks with Preelaborate is

    package Stacks is new Containers.Stacks(Value_Type);
    use Stacks;

    type Stack is new Stacks.Stack with null record;

    procedure Add(Self : in out Stack);

    procedure Subtract(Self : in out Stack);

    --So on

end Containers.Integer_Stacks;

关键是,我不想重新实现所有常见的Stack内容,只针对特定的整数堆栈。这是有效的,但留下了Containers.Integer_Stacks.StackContainers.Integer_Stacks.Stacks.Stack的丑陋和奇怪的混乱,我想避免。但是,尝试将包初始化放在私有部分中也会隐藏所有子例程。有没有更合适的方法来完成我想要做的事情,或者用户是否必须处理存在的兄弟包初始化?

替代方法: 我发现可以定义Containers.Stacks的{​​{1}}子包,如下所示:

Containers.Stacks.Integer

这很有效。除了现在我无法拨打generic with function "+"(Left, Right: Value_type) return Value_Type is <>; package Containers.Stacks.Integer is procedure Add(Self : in out Stack); end Containers.Stacks.Integer; ,我被迫拨打Stack.Add

3 个答案:

答案 0 :(得分:4)

你可以看一下

with Containers.Stacks;
generic
   type Value_Type is range <>;
   with package Basis_Stack is new Containers.Stacks (Value_Type => Value_Type);
package Containers.Integer_Stacks with Preelaborate is
   type Stack is new Basis_Stack.Stack with private;
...

这确实需要您的用户自己适当地实例化Container.Stack。

答案 1 :(得分:2)

您对解决方案的想法并不是为您提供更窄的类型,而是为了提供更多操作。

如果你想要一个更窄的类型,你碰巧在内部使用现有的类型,你可以这样做(未经测试的源):

private with Containers_Stack;

generic
   type Value_Type is range <>;
package Containers.Integer_Stack
  with Preelaborate
is
   type Instance is tagged private with null record;

   procedure Add (Item : in out Instance);
   procedure Subtract (Item : in out Instance);
private
   package Internal_Stack is new Containers.Stacks (Value_Type);

   type Instance is tagged private with
      record;
         Data : Internal_Stack.Stack;
      end record;
end Containers.Integer_Stack;

这样Containers.Integer_Stack的客户只能使用明确在包规范中列出的操作。

答案 2 :(得分:0)

由于各种原因,其他提出的答案很好,但我认为在兄弟中自动公开基本容器类型的子例程太重要了。因此,最好的答案是我最初的实施。希望其他开发人员会发现其他答案都有帮助。