Ada对象中的常量元素?

时间:2018-09-10 05:56:39

标签: ada

在Java或C#中,您通常会拥有finalreadonly的类成员-它们被设置一次,然后再也不会被触摸。它们可以为类的不同实例保留不同的值。

艾达(Ada)是否有类似的东西?因此,我试图在Ada中创建类似的内容:

package MyPackage is

   type MyObject is limited new OtherPackage.Object with private;

....

private

   type MyObject (...) is limited new OtherPackage.Object with
      record
         M_MyField : Integer := 10;
         M_MyConstantFactory : constant Factory.Object'Class := new Factory.Object;
      end record;

end MyPackage;

在声明M_MyConstantFactoryconstant components are not permitted时失败。有没有解决的办法?一位同事建议在程序包中的其他位置声明它,但这将意味着在所有实例之间共享一个M_MyConstantFactory,这不是我想要的。

我是否只需要接受设置后就可以修改值并手动防止发生这种情况的可能性?

2 个答案:

答案 0 :(得分:0)

您几乎已经有了通用的解决方案(对于不能成为判别式的情况)。该类型是私有的。软件包的客户只能通过pkg提供的操作对其进行修改。只要操作不修改有问题的字段,您就可以拥有所需的内容(除非我误解了,问题是如何防止自己修改pkg正文中的字段)。

答案 1 :(得分:0)

在回答问题之前,区分Ada和Java / C#的对象建模可能会有所帮助。在Java中,所有事物都是对象,因此所有常量都必须为final-在Ada中有些不同,Ada的对象系统(在Ada看来是“标记类型”)建立在以下两项之上:记录和类型推导。这意味着,在教授OOP时,我们可以逐步引入第一个类型派生(例如Type Degree is new Integer;),然后记录(即封装),然后是private型(即信息隐藏),最后统一所有内容和标记类型...所有这些我都假设您已经意识到。

在Ada中,constant就是这样:可以读取但[通常]不能写入的某些对象。 (例如,内存映射的IO会让事情变得有趣。)所以我们可以这样说:

Package Ex1 is
  Type Stub1 is private; -- Some type, with almost nothing public.
  C1 : Constant Stub1;   -- A constant of that type.
Private
  Type Stub1 is tagged record
    Data_1 : Integer;
    Data_2 : Float;
  end;

  -- And now we can tell the compiler what C1 _is_.
  C1: Constant Stub1 := (Data_1 => 3, Data_2 => 1.2);
End Ex1;

这就是我们在保留隐藏的实现细节的同时为标记类型创建常量的方式;不过,诚然,我们本可以公开所有内容,并删除整个private部分。

现在,我们获得了一个有趣的记录[和带标签的类型]的特性,称为判别式-这些类似于常量,而其他语言中则类似于泛型。有了判别式,我们可以根据消息长度来创建大小不同的消息类型:

Package Ex2 is
  Type Message(Length : Natural) is private; -- A message.
  Function Create( Text : String ) return Message;
Private
  Type Message(Length : Natural) is record
    Data : String(1..Length) := (Others => ' '); -- Defaults to space-filled string.
  end;

  Function Create( Text : String ) return Message is
  ( Data => Text, Length => Text'Length );
End Ex2;

现在,在这种情况下,当您进行类似X : Message := Create("Steve");的赋值时,变量类型[在此示例中不受约束,在这种情况下将被约束为Message(5)(因为“ Steve”为5个字符)因此尝试使用其他大小的消息字符串进行重新分配将不起作用。 (因此,虽然您不能说X:= Create("Why"),但您却不能说X:= Create("Hello"),因为这里的判别式[Length是5。)判别式在某些情况下可以像常量字段一样工作。

limited关键字表示该类型没有赋值[但是确实具有初始化],因此您可以使整个类型表现为常量;不过,这与将一个成分设为constant有所不同,肯定不会像TT'Class之间的区别那样微妙(T'Class是类型T,从中派生的所有类型,其中T 该类型。)