Ada中标记记录中的私有属性

时间:2014-09-17 09:20:46

标签: oop ada gnat

从面向对象的范例思考,人们如何倾向于为标记记录实现私有属性?

从我所看到的那一刻起,唯一的方法就是拥有一个属于私人类型的属性。

例如

type car is tagged record
  i_am_a_public_attribute : Integer;
  i_am_another_public_attribute : Integer;
  my_private_attributes : t_private_attributes;
end record;

其中t_private_attributes在包的私有部分中声明。

我想到的第二种方式是使用继承,例如

type car_public is tagged record
  i_am_a_public_attribute : Integer;
  i_am_another_public_attribute : Integer;
end record;

type car_private is new car_public with record
  my_private_attributes : Integer;
end record;

其中car_private在包的私有部分中声明。虽然我觉得这个实现会非常混乱。

人们如何倾向于这样做?

谢谢马特

2 个答案:

答案 0 :(得分:5)

Ada中的包的私有部分更接近C ++中的受保护,而不是私有。 大多数情况下,使用私有部分是最好的方法,此外还提供了将单元测试编写为子包的灵活性,以便他们可以测试该类型的属性。

如果您真的想让属性无法访问代码的任何其他部分,则必须在您的身体中定义它们。这可以使用在包的私有部分中声明的不完整类型来完成,然后在正文中完成。然后,您的类型将包含指向此不完整类型的指针,如:

package Foo is
    type My_Type is tagged private;
private
   type Private_Part;
   type Private_Part_Access is access Private_Part;
   type My_Type is tagged record
       P : Private_Part_Access;
   end record;
end Foo;
package body Foo is
   type Private_Part is record
      ...
   end record;
end Foo;

这也可以通过将Private_Part作为抽象标记的空记录来完成,并将其扩展到正文中。

当然,这种方案的难点在于内存管理,因为你必须确保你的对象确实释放相应的内存(可能通过使用受控类型)。

答案 1 :(得分:1)

这是Brian Drummond在上述评论中所写的扩展。当我使用Ada编程语言进行OOP并希望表达具有一些私有和公共属性的“类”的想法时,我会写(使用Matt的例子):

type Car_Type is tagged private;

function I_Am_A_Public_Attribute (This : Car_Type)       return Integer;
function I_Am_Another_Public_Attribute (This : Car_Type) return Integer;

private

type Car_Type is tagged
   record
      I_Am_A_Public_Attribute        : Integer;
      I_Am_Another_Public_Attribute  : Integer;
      I_Am_A_Private_Attribute       : Integer;
      I_Am_Another_Private_Attribute : Integer;
   end record;

function I_Am_A_Public_Attribute (This : Car_Type)       return Integer is (This.I_Am_A_Public_Attribute);
function I_Am_Another_Public_Attribute (This : Car_Type) return Integer is (This.I_Am_Another_Public_Attribute);

我们的想法是为每个想要公开的属性设置一个get函数。实际上,上面的代码并不是我所说的“Ada风格”。要利用Ada的优势,请为每个属性定义一个新类型:

type I_Am_A_Public_Attribute_Type        is new Integer;
type I_Am_Another_Public_Attribute_Type  is new Integer;

type Car_Type is tagged private;

function I_Am_A_Public_Attribute (This : Car_Type)       return I_Am_A_Public_Attribute_Type;
function I_Am_Another_Public_Attribute (This : Car_Type) return I_Am_Another_Public_Attribute_Type;

private

type I_Am_A_Private_Attribute_Type       is new Integer;
type I_Am_Another_Private_Attribute_Type is new Integer;

type Car_Type is tagged
   record
      I_Am_A_Public_Attribute        : I_Am_A_Public_Attribute_Type;
      I_Am_Another_Public_Attribute  : I_Am_Another_Public_Attribute_Type;
      I_Am_A_Private_Attribute       : I_Am_A_Private_Attribute_Type;
      I_Am_Another_Private_Attribute : I_Am_Another_Private_Attribute_Type;
   end record;

function I_Am_A_Public_Attribute (This : Car_Type)       return I_Am_A_Public_Attribute_Type        is (This.I_Am_A_Public_Attribute);
function I_Am_Another_Public_Attribute (This : Car_Type) return I_Am_Another_Public_Attribute_Type  is (This.I_Am_Another_Public_Attribute);

请注意,如果将get函数与错误的属性混合,则会出现编译时错误。这是“Ada,我们信任的强力打字”的一个很好的例子。

编辑:一旦我从性能角度调查了公共属性和get-functions之间的选择是否有任何偏好。我发现使用GNAT编译器时性能没有差异。我没有尝试过与任何其他编译器相同的实验。