在 Ada 中,为什么 child 没有用泛型 parent 实例化,为什么我也必须使它成为泛型?
In Ada, why doesn't a child get instantiated with the generic parent and why do I have to make it generic as well?
我有一个带有一些通用接口的 parent 包。我现在想创建此接口的多个实现,每个都在不同的文件中。我想我可以简单地将这些包 children 到包含接口的包,实例化通用然后直接访问 child 包,但这给了我一个错误 child包也必须是通用的。
这导致我进行以下实施:
parent.ads:
generic
type T is private;
package Parent is
type I_Generic is interface;
type Any_Generic is access all I_Generic'Class;
function Get (This : in out I_Generic) return T is abstract;
procedure Set (This : in out I_Generic; Value : T) is abstract;
end Parent;
parent-child.广告:
generic
package Parent.Child is
-- long spec
type Impl is new I_Generic with private;
type Impl_Access is access all Impl;
overriding function Get (This : in out Impl) return T;
overriding procedure Set (This : in out Impl; Value : T);
private
type Impl is new I_Generic with
record
Data : T;
end record;
end Parent.Child;
parent-child.adb:
package body Parent.Child is
-- long body
overriding
function Get (This : in out Impl) return T is
begin
return This.Data;
end Get;
overriding
procedure Set (This : in out Impl; Value : T) is
begin
This.Data := Value;
end Set;
end Parent.Child;
tester.adb:
with Ada.Text_IO;
with Parent;
with Parent.Child;
package body Tester is
package Parent_Inst is new Parent (T => Integer);
package Child_Inst is new Parent_Inst.Child;
procedure Test is
Instance : constant Child_Inst.Impl_Access := new Child_Inst.Impl;
Polymorphic : constant Parent_Inst.Any_Generic := Parent_Inst.Any_Generic (Instance);
begin
Instance.Set (42);
Ada.Text_IO.Put_Line (Polymorphic.Get'Img);
end Test;
end Tester;
结果:
42
为什么我需要将 child 包设为通用包,然后先创建它的实例?为什么我不能简单地使用 Instance : Parent_Inst.Child.Impl_Access := new Parent_Inst.Child.Impl;
?
有什么方法可以让我更干净吗?也许我忽略了一个更简单且没有这个问题的需求的不同解决方案?还是这只是实现我所描述内容的方法,我是否应该接受额外包实例化的冗长?在我自己的代码中,我现在必须为每个接口实现包进行多个包实例化,这会导致许多额外的代码行。
子包必须是通用的,因为 LRM 10.1.1, 17/3:
A child of a generic library package shall either be itself a generic unit or be a renaming of some other child of the same generic unit.
这是必要的,因为子包可以访问父单元的通用参数值,除非实例化父单元,否则该值不存在。
现在在 Ada 中,泛型实例化是显式的,每个实例化只实例化一个泛型单元。在你的情况下,
package Parent_Inst is new Parent (T => Integer);
实例化 Parent
包。它 不 实例化 Parent.Child
因为那是一个单独的通用单元。因此,您确实需要单独实例化Child
。
您可以编写一个一次实例化所有的帮助程序包,例如
generic
type T is private;
package Everything is
package Parent_Inst is new Parent (T);
package Child_Inst is new Parent_Inst.Child;
end Everything;
然后在需要实例的地方实例化Everything
。
我有一个带有一些通用接口的 parent 包。我现在想创建此接口的多个实现,每个都在不同的文件中。我想我可以简单地将这些包 children 到包含接口的包,实例化通用然后直接访问 child 包,但这给了我一个错误 child包也必须是通用的。
这导致我进行以下实施:
parent.ads:
generic
type T is private;
package Parent is
type I_Generic is interface;
type Any_Generic is access all I_Generic'Class;
function Get (This : in out I_Generic) return T is abstract;
procedure Set (This : in out I_Generic; Value : T) is abstract;
end Parent;
parent-child.广告:
generic
package Parent.Child is
-- long spec
type Impl is new I_Generic with private;
type Impl_Access is access all Impl;
overriding function Get (This : in out Impl) return T;
overriding procedure Set (This : in out Impl; Value : T);
private
type Impl is new I_Generic with
record
Data : T;
end record;
end Parent.Child;
parent-child.adb:
package body Parent.Child is
-- long body
overriding
function Get (This : in out Impl) return T is
begin
return This.Data;
end Get;
overriding
procedure Set (This : in out Impl; Value : T) is
begin
This.Data := Value;
end Set;
end Parent.Child;
tester.adb:
with Ada.Text_IO;
with Parent;
with Parent.Child;
package body Tester is
package Parent_Inst is new Parent (T => Integer);
package Child_Inst is new Parent_Inst.Child;
procedure Test is
Instance : constant Child_Inst.Impl_Access := new Child_Inst.Impl;
Polymorphic : constant Parent_Inst.Any_Generic := Parent_Inst.Any_Generic (Instance);
begin
Instance.Set (42);
Ada.Text_IO.Put_Line (Polymorphic.Get'Img);
end Test;
end Tester;
结果:
42
为什么我需要将 child 包设为通用包,然后先创建它的实例?为什么我不能简单地使用 Instance : Parent_Inst.Child.Impl_Access := new Parent_Inst.Child.Impl;
?
有什么方法可以让我更干净吗?也许我忽略了一个更简单且没有这个问题的需求的不同解决方案?还是这只是实现我所描述内容的方法,我是否应该接受额外包实例化的冗长?在我自己的代码中,我现在必须为每个接口实现包进行多个包实例化,这会导致许多额外的代码行。
子包必须是通用的,因为 LRM 10.1.1, 17/3:
A child of a generic library package shall either be itself a generic unit or be a renaming of some other child of the same generic unit.
这是必要的,因为子包可以访问父单元的通用参数值,除非实例化父单元,否则该值不存在。
现在在 Ada 中,泛型实例化是显式的,每个实例化只实例化一个泛型单元。在你的情况下,
package Parent_Inst is new Parent (T => Integer);
实例化 Parent
包。它 不 实例化 Parent.Child
因为那是一个单独的通用单元。因此,您确实需要单独实例化Child
。
您可以编写一个一次实例化所有的帮助程序包,例如
generic
type T is private;
package Everything is
package Parent_Inst is new Parent (T);
package Child_Inst is new Parent_Inst.Child;
end Everything;
然后在需要实例的地方实例化Everything
。