【发布时间】:2021-01-05 22:21:03
【问题描述】:
我有一个带有一些通用接口的父包。我现在想创建这个接口的几个实现,每个实现都在不同的文件中。我以为我可以简单地将这些包作为包含接口的包的子包,实例化泛型,然后直接访问子包,但这给了我一个错误,即子包也必须是泛型的。
这导致我进行以下实现:
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.ads:
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
为什么我需要先将子包设为通用,然后再创建它的实例?为什么我不能简单地使用Instance : Parent_Inst.Child.Impl_Access := new Parent_Inst.Child.Impl;?
有什么方法可以让我更清洁吗?也许我忽略了一个不同的解决方案来满足我的要求,它更简单并且没有这个问题?或者这仅仅是实现我所描述的方式,我应该接受额外包实例化的冗长吗?在我自己的代码中,我现在必须为每个接口实现包创建几个包实例化,这会导致很多额外的代码行。
【问题讨论】:
-
子包是通用的似乎很自然,因为它明确使用通用参数
T。 -
我同意,但是因为我已经在创建一个已经填写了相同参数 T 的父包的实例,所以我想知道为什么我仍然需要创建子包的实例,而不任何附加参数,以便能够访问子包内的对象。难道没有某种方法可以在一个实例中实现所有这些吗?我可以想象如果实现是嵌套包我不会有这个问题,但是我必须将所有实现放在父级中。我希望它们是单独的文件。
-
我认为 Ada 允许在多个单独的文件中实现包。见How do I use “separate" keyword
标签: generics package instance ada