0

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

目前,从我所见,唯一的方法是拥有一个私有类型的属性。

例如

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 在包的私有部分中声明。虽然我认为这个实现会非常混乱。

人们如何倾向于这样做?

谢谢马特

4

2 回答 2

5

在 Ada 中,包的私有部分更接近于 C++ 中的 protected,而不是 private。大多数时候,使用私有部分是最好的方法,此外还提供了将单元测试作为子包编写的灵活性,以便他们可以测试类型的属性。

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

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 成为抽象标记的空记录并在正文中扩展它来完成。

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

于 2014-09-17T12:05:42.420 回答
2

这是布赖恩·德拉蒙德在上述评论中所写内容的扩展。当我在 Ada 编程语言中进行 OOP 并希望表达具有一些私有和公共属性的“类”的想法时,我会写(使用马特的例子):

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);

这个想法是为每个想要公开的属性设置一个获取函数。实际上,上面的代码并不是我所说的“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-function 与错误的属性混合在一起,则会出现编译时错误。这是“Ada,我们信任强类型”的一个很好的例子。

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

于 2014-09-20T23:01:32.653 回答