Generics 在Ada中,为什么';一个孩子不能用泛型父对象实例化,为什么我也要使它泛型?

Generics 在Ada中,为什么';一个孩子不能用泛型父对象实例化,为什么我也要使它泛型?,generics,package,instance,ada,Generics,Package,Instance,Ada,我有一个带有一些通用接口的父包。现在,我想创建此接口的几个实现,每个实现位于不同的文件中。我认为我可以简单地将这些包作为包含接口的包的子包,实例化泛型,然后直接访问子包,但这给了我一个错误,即子包也必须是泛型的 这导致我采取以下措施: 家长广告: generic type T is private; package Parent is type I_Generic is interface; type Any_Generic is access all I_Generic'

我有一个带有一些通用接口的父包。现在,我想创建此接口的几个实现,每个实现位于不同的文件中。我认为我可以简单地将这些包作为包含接口的包的子包,实例化泛型,然后直接访问子包,但这给了我一个错误,即子包也必须是泛型的

这导致我采取以下措施:

家长广告:

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;
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;
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;
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
亲子关系。广告:

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;
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;
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;
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
父子关系。亚洲开发银行:

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;
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;
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;
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
tester.adb:

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;
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;
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;
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
结果:

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;
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;
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;
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
为什么我需要使子包通用,然后首先创建它的实例?为什么我不能简单地使用
实例:Parent\u Inst.Child.Impl\u Access:=new Parent\u Inst.Child.Impl


我有办法洗这个吗?也许我忽略了一个与我的需求不同的解决方案,它更简单并且没有这个问题?或者这仅仅是实现我所描述内容的方法,我应该接受额外包实例化的冗长吗?在我自己的代码中,我现在必须为每个接口实现包进行几个包实例化,这会产生许多额外的代码行。

子包必须是通用的,因为:

通用库包的子项本身应为通用单元,或者是相同通用单元的其他子项的重命名

这是必要的,因为子包可以访问父单元的泛型参数的值,除非父单元被实例化,否则该值不存在

现在在Ada中,泛型实例化是显式的,每个实例化只实例化一个泛型单元。就你而言

package Parent_Inst is new Parent (T => Integer);
实例化父级
包。它不实例化父.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;

然后在需要实例的地方实例化
所有内容

子包是泛型的似乎很自然,因为它显式地使用泛型参数
T
。我同意,但由于我已经在创建父包的实例,并且已经填充了相同的参数T,我想知道为什么我仍然需要在没有任何附加参数的情况下创建子包的实例,以便能够访问子包中的对象。难道没有办法在一次实例化中实现所有这些吗?我可以想象,如果实现是嵌套包,我就不会有这个问题,但是我必须将所有实现放在父级中。我希望它们是单独的文件。我认为Ada允许包在多个单独的文件中实现。这很好地解释了为什么我需要创建单独的实例,谢谢!另外,这个助手包解决了我的冗长问题。我确实需要在这里添加具体的实现,但由于99%的情况下都是相同的设置,这让一切变得更加干净,再次感谢:)