2013-10-11 82 views
2

我试图用受保护的对象包装散列映射,以便可以通过多个任务来访问它。我希望受保护类型的过程可用,但将散列映射和元素记录定义移动到软件包专用部分会很好。从Ada的受保护对象访问私有类型

示例代码在这里:

package Thing_Protected is 

    type Thing_Info is record 
     Key : Ada.Strings.Unbounded.Unbounded_String; 
     Counter_Value : Natural := 0; 
    end record; 

    package Thing_Info_Maps is new Ada.Containers.Hashed_Maps 
     (Key_Type => Ada.Strings.Unbounded.Unbounded_String, 
     Element_Type => Thing_Info, 
     Hash => Ada.Strings.Unbounded.Hash, 
     Equivalent_Keys => Ada.Strings.Unbounded."="); 

    protected type Thing is 
     procedure Increment (Key : String); 
     procedure Another_Thing (Key : String); 
    private 
     Thing_Map : Thing_Info_Maps.Map; 
    end Thing; 

private 

    -- move Thing_Info, Thing_info_maps into here. 

end Thing_Protected; 

我试图定义Thing_Info为私有类型..但我不知道我会如何定义Thing_Info_Maps包作为私人使用,但仍然来自保护对象访问类型。

所以我真的不会发现试图找到一种方式来获得这样的事:

package Thing_Protected is 

    type Thing_Info is private; 
    package Thing_Info_Maps is private; 

    protected type Thing is 
     procedure Increment (Key : String); 
     procedure Another_Thing (Key : String); 
    private 
     Thing_Map : Thing_Info_Maps.Map; -- <<- how would we know about .Map?? 
    end Thing; 

private 

    type Thing_Info is record 
     Key : Ada.Strings.Unbounded.Unbounded_String; 
     Counter_Value : Natural := 0; 
    end record; 

    package Thing_Info_Maps is new Ada.Containers.Hashed_Maps 
     (Key_Type => Ada.Strings.Unbounded.Unbounded_String, 
     Element_Type => Thing_Info, 
     Hash => Ada.Strings.Unbounded.Hash, 
     Equivalent_Keys => Ada.Strings.Unbounded."="); 

end Thing_Protected; 
+0

我编辑了自己的冠军。请参阅:“[应该在其标题中包含”标签“](http://meta.stackexchange.com/questions/19190/)”,其中的共识是“不,他们不应该”。 –

+0

我想现在它不像ada相关那么明显。尤其是在排名前15的投票标题为“ada”的问题中,只有一个在标题中没有Ada。 –

+0

我会照顾的。 –

回答

7

随着2005年的Ada,你可以使用一个保护的接口:

package Thing_Protected is 

    type Thing is protected interface; 

    procedure Increment  (Object : in out Thing; Key : String) is abstract; 
    procedure Another_Thing (Object : in out Thing; Key : String) is abstract; 

    -- As the implementation type is private, we need a 
    -- factory method which returns an instance of the 
    -- implementation type: 
    function Create return Thing'Class; 

private 

    type Thing_Info is record 
     Key : Ada.Strings.Unbounded.Unbounded_String; 
     Counter_Value : Natural := 0; 
    end record; 

    package Thing_Info_Maps is new Ada.Containers.Hashed_Maps 
     (Key_Type => Ada.Strings.Unbounded.Unbounded_String, 
     Element_Type => Thing_Info, 
     Hash => Ada.Strings.Unbounded.Hash, 
     Equivalent_Keys => Ada.Strings.Unbounded."="); 

    protected type Thing_Impl is new Thing with 
     overriding procedure Increment (Key : String); 
     overriding procedure Another_Thing (Key : String); 
    private 
     Thing_Map : Thing_Info_Maps.Map; 
    end Thing_Impl; 

end Thing_Protected; 
+0

这是一个很好的答案,但我不完全确定如何实现Create函数。我设法通过返回一个Thing'Class来访问它。试图返回一个Thing'Class给我有趣的错误,如“初始化有限对象需要聚集或函数调用”或“期望类型”Thing_Impl“定义在......,找到一个复合类型”这是因为同步接口是有限类型所以不能复制? –

+0

啊,我想我明白了。我需要使用扩展返回语句:http://www.adacore.com/adaanswers/gems/ada-gem-10/ –

+0

受保护的类型固有地受到限制,受保护的接口也是如此。你一定可以在没有延期退货声明的情况下工作,但由于我不知道你所尝试的是什么,我不能告诉你你做错了什么。 – flyx

2

how would we know about .Map??

怎么这样呢?

Generic 
    type Thing_Info is private; 
    with package Thing_Info_Maps is new Ada.Containers.Hashed_Maps(
      Key_Type  => Ada.Strings.Unbounded.Unbounded_String, 
      Element_Type => Thing_Info, 
      Hash   => Ada.Strings.Unbounded.Hash, 
      Equivalent_Keys => Ada.Strings.Unbounded."="); 
Package INFO is 

    protected type Thing is 
     procedure Increment  (Key : String); 
     procedure Another_Thing (Key : String); 
    private 
     -- BEHOLD THE POWER OF GENERICS!! 
     Thing_Map : Thing_Info_Maps.Map; 
    end Thing; 

Private 
    -- PRIVATE STUFF 
End INFO; 
+0

这是不是仍然把hashed_map放在包界面中?我想我想公开提供Increment()和Another_Thing(),但用户不需要知道我在幕后使用HashMap。 –

+0

它是;我想你可以把'Thing'本身变成一个私有类型,并且在规范中有'procedure Increment(Item:in Thing; Key:String)',在主体中重命名/包装或者有一个私有类型'Thing_Map',它是'Thing_Info_Maps'的子类型重命名... – Shark8

2

执行此包的用户需要知道那里有一个受保护的类型?如果没有,你可以声明与原始子程序规范的可见部分(标记)类型匹配:

package Thing_Protected is 

    type Thing is tagged limited private; 
    procedure Increment (This : in out Thing; Key : String); 
    procedure Another_Thing (This : in out Thing; Key : String); 

private 

    type Thing_Info is record 
     Key : Ada.Strings.Unbounded.Unbounded_String; 
     Counter_Value : Natural := 0; 
    end record; 

    package Thing_Info_Maps is new Ada.Containers.Hashed_Maps 
    (Key_Type => Ada.Strings.Unbounded.Unbounded_String, 
     Element_Type => Thing_Info, 
     Hash => Ada.Strings.Unbounded.Hash, 
     Equivalent_Keys => Ada.Strings.Unbounded."="); 

    protected type Thing_Imp is 
     procedure Increment (Key : String); 
     procedure Another_Thing (Key : String); 
    private 
     Thing_Map : Thing_Info_Maps.Map; 
    end Thing_Imp; 

    type Thing is tagged limited record 
     Imp : Thing_Imp; 
    end record; 

end Thing_Protected; 

与身体像

package body Thing_Protected is 

    procedure Increment (This : in out Thing; Key : String) is 
    begin 
     This.Imp.Increment (Key); 
    end Increment; 

    procedure Another_Thing (This : in out Thing; Key : String) is 
    begin 
     This.Imp.Another_Thing (Key); 
    end Another_Thing; 

    protected body Thing_Imp is 
     procedure Increment (Key : String) is 
     N : constant Ada.Containers.Count_Type := Thing_Map.Length; 
     begin 
     null; 
     end Increment; 
     procedure Another_Thing (Key : String) is 
     begin 
     null; 
     end Another_Thing; 
    end Thing_Imp; 

end Thing_Protected;