我有一个基本类型,其工作是维护一个项目列表。它具有非调度功能,可以向其添加项目,以及从中检索项目列表。
从这个基础派生的类型……
我认为麻烦就是这样 Bases.Add_To 没有令人愉快,标准的方式知道要追加什么 Base 记录(用 Size 递增)以复制实际的特定于类的数据 This 。
Bases.Add_To
Base
Size
This
我想你可以用未经检查的转换来解决问题。或许,通过使用,构建记录 Ada.Tags.Generic_Dispatching_Constructor ( 这里 , 这里 );但这似乎是一个坏主意。
Ada.Tags.Generic_Dispatching_Constructor
我知道它需要更多的工作,但你也可以改变Add_To使用Base而不是Base'Class。然后,您必须为具有多个空记录扩展名的任何派生类型覆盖它,但您将获得所需的静态数组结果。派生的实现类似于您实现Create的方式。
示例(我修改了派生类以强制使用非空记录扩展 编译器要求您派生操作:
with Ada.Text_IO; use Ada.Text_IO; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; procedure Hello is package Bases is type Base (<>) is tagged private; -- I want to hide the size type Int_List is array (Positive range <>) of Integer; -- as an example function Create return Base; -- returns an empty Base function Add_To (This : Base; I : Integer) return Base; -- Append function Image (This : Base) return String; -- Dispatching example function List (This : Base'Class) return Int_List; -- Get the data for internal use private type Base (Size : Natural) is tagged record Ints : Int_List (1 .. Size); end record; end Bases; package body Bases is function Create return Base is (Size => 0, Ints => (others => 0)); function Add_To (This : Base; I : Integer) return Base is -- This is where I have trouble: "aggregate cannot be of a class-wide type" Copy : Base := (Size => This.Size + 1, Ints => This.Ints & I); begin return Copy; end Add_To; function Image (This : Base) return String is ("BASE"); function List (This : Base'Class) return Int_List is (This.Ints); end Bases; package Deriveds is type Derived is new Bases.Base with record Value : Integer; end record; function Create return Derived; function Add_To(This : Derived; I : Integer) return Derived; function Image (This : Derived) return String; end Deriveds; package body Deriveds is function Create return Derived is (Bases.Create with Value => 0); function Image (This : Derived) return String is Result : Unbounded_String; Ints : Bases.Int_List := This.List; begin for I in Ints'Range loop Result := Result & Integer'Image (Ints (I)); end loop; return To_String (Result); end Image; function Add_To(This : Derived; I : Integer) return Derived is begin return (Bases.Base(This).Add_To(I) with Value => This.Value); end Add_To; end Deriveds; use Deriveds; d0 : Derived := Create; d1 : Derived := d0.Add_To(1).Add_To(3); d2 : Derived := d1.Add_To(2); begin Put_Line(d2.Image); end Hello;