将地图传递给普通程序

Passing map to common procedure

Java 编程语言经常使用像 java.util.Map 这样的接口。

在以下示例中,使用通用包 Ada.Containers.Hashed_MapsAda.Containers.Ordered_Maps 创建了两个自定义地图包。两个通用包都提供 functions/procedures ClearLength。程序 Do_Something 正在使用此 functions/procedures 清除传递的地图并打印容器长度(愚蠢的例子...)。

我是对的,那么不可能创建一个程序 Do_Something_Special 来接受两种类型的映射 Map_One.MapMap_Two.Map?在 Java 中,可以定义类型为 Map<Natural, Unbounded_String>.

的参数
with Ada.Containers.Hashed_Maps;
with Ada.Containers.Ordered_Maps;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO;

procedure Main is
   function Hash (Value : Natural) return Ada.Containers.Hash_Type is
   begin
      return Ada.Containers.Hash_Type (Value);
   end Hash;

   package Map_One is new Ada.Containers.Hashed_Maps
     (Key_Type        => Natural,
      Element_Type    => Unbounded_String,
      Hash            => Hash,
      Equivalent_Keys => "=");

   package Map_Two is new Ada.Containers.Ordered_Maps
     (Key_Type     => Natural,
      Element_Type => Unbounded_String);

   procedure Do_Something (Input : in out Map_One.Map) is
   begin
      Input.Clear;

      Ada.Text_IO.Put_Line ("Length: " & Input.Length'Image);
   end Do_Something;

   procedure Do_Something (Input : in out Map_Two.Map) is
   begin
      Input.Clear;

      Ada.Text_IO.Put_Line ("Length: " & Input.Length'Image);
   end Do_Something;

   procedure Do_Something_Special (Input : in out ???) is
   begin
      Input.Clear;

      Ada.Text_IO.Put_Line ("Length: " & Input.Length'Image);
   end Do_Something_Special;
begin
   null;
end Main;

就像在 Java 中一样,您可以使用泛型或接口。

一个通用的唯一解决方案:

generic
    type Map is private;
    with procedure Clear(Self : in out Map);
    with function Length(Self : Map) return Ada.Containers.Count_Type;
procedure Do_Something_Special(Input : in out Map);
procedure Do_Something_Special(Input : in out Map) is
begin
    Clear(Input);
    Ada.Text_IO.Put_Line("Length: " & Length(Input)'Image);
end Do_Something_Special;

procedure Do_Something_Map_One is new Do_Something_Special
    (Map    => Map_One.Map,
     Clear  => Map_One.Clear,
     Length => Map_One.Length);

procedure Do_Something_Map_Two is new Do_Something_Special
    (Map    => Map_Two.Map,
     Clear  => Map_Two.Clear,
     Length => Map_Two.Length);

如果您想走使用地图界面的路线,您可以执行以下操作:

为任何 key/value 类型创建通用接口

use Ada.Containers;

generic
    type Key_Type is private;
    type Element_Type is private;
package Map_Interfaces is

    type Map_Interface is interface;
    procedure Clear(Self : in out Map_Interface) is abstract;
    function Length(Self : Map_Interface) return Count_Type is abstract;

    -- other operations

end Map_Interfaces;

接下来为您想要的 key/value 类型实现它:

package My_Map_Interfaces is new Map_Interfaces
    (Key_Type     => Natural,
     Element_Type => Unbounded_String);

use My_Map_Interfaces;

现在您可以使用 class 类型的接口在任何实现该接口的地图上操作:

procedure Do_Something_Special_1(Input : in out Map_Interface'Class) is
begin
    Input.Clear;
    Ada.Text_IO.Put_Line ("Length: " & Input.Length'Image);
end Do_Something_Special_1;

那么你只需要扩展 Ada 映射类型并实现接口:

type Map_1 is new Map_One.Map and Map_Interface with null record;
type Map_2 is new Map_Two.Map and Map_Interface with null record;

M1 : Map_1;
M2 : Map_2;

你可以这样称呼它:

Do_Something_Special_1(M1);
Do_Something_Special_1(M2);

或者如果您想要静态分派而不是动态分派,您可以创建另一个通用函数:

generic
    type Map is new Map_Interface with private;
procedure Do_Something_Special_2(Input : in out Map);

procedure Do_Something_Special_2(Input : in out Map) is
begin
    Input.Clear;
    Ada.Text_IO.Put_Line ("Length: " & Input.Length'Image);
end Do_Something_Special_2;

procedure Do_Something_Map_1 is new Do_Something_Special_2(Map_1);
procedure Do_Something_Map_2 is new Do_Something_Special_2(Map_2);

并这样称呼它:

Do_Something_Map_1(M1);
Do_Something_Map_2(M2);