从面向对象的范例思考,人们如何倾向于为标记记录实现私有属性?
从我所看到的那一刻起,唯一的方法就是拥有一个属于私人类型的属性。
例如
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在包的私有部分中声明。虽然我觉得这个实现会非常混乱。
人们如何倾向于这样做?
谢谢马特
答案 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编译器时性能没有差异。我没有尝试过与任何其他编译器相同的实验。