Ada通用包扩展

3

我有一个通用包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;
重点是,我不想重新实现所有常见的栈操作,只为特定的整数栈。这个方法可以工作,但会留下一个丑陋而奇怪的混乱部分:Containers.Integer_Stacks.StackContainers.Integer_Stacks.Stacks.Stack,我想避免这种情况。然而,试图将包初始化放在私有部分中也会隐藏所有子例程。是否有更适当的方法来完成我所要做的事情,还是用户必须处理存在兄弟包初始化的情况? 替代方法: 我发现可以定义一个名为Containers.Stacks.IntegerContainers.Stacks子包,如下所示:
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,只能强制调用Add(Stack)

3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
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;
...

这确实需要用户自己适当地实例化Containers.Stacks。


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 的客户端只能使用您在包规范中明确列出的操作。


尝试将包初始化放在私有部分,但这也会隐藏所有子程序。 - Patrick Kelly
是的,这正是你所做的整个目的,就像你写的那样,你想创建一个“狭窄目的的堆栈”。你仍然可以从Containers.Stacks.Stack中公开使用你需要的操作的公共版本,以满足你的“狭窄目的堆栈”的需求。 - Jacob Sparre Andersen

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,