Ada 通用包扩展
Ada Generic Package Extension
我有一个通用包 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.Stack
和 Containers.Integer_Stacks.Stacks.Stack
的丑陋和奇怪的混乱,我想避免这种情况。然而,试图将包初始化放在私有部分也会隐藏所有子例程。是否有更合适的方法来完成我正在尝试做的事情,或者用户是否必须处理存在的兄弟包初始化?
替代方法:
我发现可以像这样定义一个名为 Containers.Stacks.Integer
的 Containers.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)
。
你可以看看
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。
您的解决方案想法不是给您一个更窄的类型,而是一个具有 更多 操作的类型。
如果你想要一个更窄的类型,你碰巧在内部使用现有类型,你可以这样做(未经测试的来源):
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
的客户只能使用您 明确 在包规范中列出的操作。
由于各种原因,其他建议的答案都很好,但我认为在同级中自动公开基本容器类型的子例程太重要了。因此,最好的答案是我的初步实施。希望其他开发人员会发现其他答案有帮助。
我有一个通用包 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.Stack
和 Containers.Integer_Stacks.Stacks.Stack
的丑陋和奇怪的混乱,我想避免这种情况。然而,试图将包初始化放在私有部分也会隐藏所有子例程。是否有更合适的方法来完成我正在尝试做的事情,或者用户是否必须处理存在的兄弟包初始化?
替代方法:
我发现可以像这样定义一个名为 Containers.Stacks.Integer
的 Containers.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)
。
你可以看看
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。
您的解决方案想法不是给您一个更窄的类型,而是一个具有 更多 操作的类型。
如果你想要一个更窄的类型,你碰巧在内部使用现有类型,你可以这样做(未经测试的来源):
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
的客户只能使用您 明确 在包规范中列出的操作。
由于各种原因,其他建议的答案都很好,但我认为在同级中自动公开基本容器类型的子例程太重要了。因此,最好的答案是我的初步实施。希望其他开发人员会发现其他答案有帮助。