【发布时间】:2021-07-05 07:57:53
【问题描述】:
为了减少测试和重复代码,我发现了通过泛型混入的多重继承,但我不知道实现这一目标的最佳方法以及最佳实践。
具有以下类层次结构示例(使用diagrams.net 完成):
这是泛型的规范:
generic
type S is abstract tagged private;
package GenericChild is
type GenericChild_T is abstract new S with private;
procedure P_SetGenericAttribute (Self : in out GenericChild_T;
i : Integer);
function F_GetGenericAttribute (Self : GenericChild_T)
return Integer;
private
type GenericChild_T is abstract new S with
record
GenericAttribute : Integer;
end record;
end GenericChild;
对于 Child1 中的泛型实例化:
with Root;
with GenericChild;
package Child1 is
type Child1_T is new Root.Root_T with private;
private
package Child1_G is new GenericChild (Root.Root_T);
type Child1_T is new Child1_G.GenericChild_T with null record;
end package Child1;
我可以毫无问题地使用在 Root_T 类上定义的方法,但是,当我尝试使用我得到的通用方法时:
no selector "P_SetGenericAttribute" for private type "Child1_T" ...
这是我测试过的 main.adb:
with Child1;
procedure Main is
Instance : Child1.Child1_T;
begin
Instance.P_SetRootAttribute(1); --ok
Instance.P_SetGenericAttribute(1); --illegal
end main;
为什么?因为我已经封装了通用包实例化? 在那种情况下,最好的解决方法是什么?在子类中创建公共方法并在方法实现中调用私有通用实例化方法?因为我想将通用实例化保持为私有。通过这样做,我可以设置和获取泛型的属性。
这些是对 child1.ads 执行的更改,适用于我:
with Root;
with GenericChild;
package Child1 is
type Child1_T is new Root.Root_T with private;
procedure P_SetGenericAttribute (Self : in out Child1_T;
i : Integer);
function F_GetGenericAttribute (Self : Child1_T)
return Integer;
private
package Child1_G is new GenericChild (Root.Root_T);
type Child1_T is new Child1_G.GenericChild_T with null record;
end package Child1;
这是完成它并工作的child1.adb,但我不确定它是否是实现它的更好方法,例如重命名或其他:
package body Child1 is
procedure P_SetGenericAttribute (Self : in out Child1_T;
i : Integer) is
begin
Child1_G.GenericChild_T(Self).P_SetGenericAttribute (i);
end P_SetGenericAttribute;
function F_GetGenericAttribute (Self : Child1_T)
return Integer is
i : Integer;
begin
i := Child1_G.GenericChild_T(Self).F_GetGenericAttribute;
return i;
end F_GetGenericAttribute;
end package Child1;
欢迎任何建议和/或最佳做法。
【问题讨论】:
-
请显示引发“无选择器”错误消息的代码(及其上下文)。包 Child1 的私有部分在那里可见吗?
-
@NiklasHolsti 我已经添加了引发错误的主要内容;这是我对错误的思考,因为我已经封装了泛型实例化,所以我不能真正使用泛型公共方法,因为实例化是私有的,但是 GNAT Studio 将这些泛型方法显示为好像它们是公共的,而 IDE 确实不显示继承的,这是一个错误。
-
我不明白你到底在说什么“错误”,但显然 Main 没有包 Child1 的私有部分的可见性,因此 Main 仅将 Instance 视为Root_T,GenericChild 中定义的操作在 Main 中是不可见的。
-
@NiklasHolsti 该错误在 GNAT Studio 中,如您所说,它显示了私有通用实例化的方法,而不是从 Root_T 继承的方法。我认为行为没问题,但我想确认它是否是由于私有实例化或什么引起的,你已经确认了。现在,这个问题通常是如何解决的?因为我想封装通用实例化,但我希望它们的公共方法也可以使用。为在内部调用泛型实例化方法的 Child1_T 类型编写公共方法工作正常,但我不确定是否是通常的方式
-
@Albatros23 最初的答案似乎是:是的。如果你将泛型的实例放在某个包的私有部分,那么你需要添加公共函数来访问这个泛型实例。但是,为了能够给出更明确的答案,如果您可以为您提到的“通过通用混合进行多重继承”模式添加一些解释性参考和/或显示此模式的实际问题,这将是有帮助的成为一个解决方案。这种“通过通用混入实现多重继承”模式解决的实际问题,至少在我看来,并不完全清楚。
标签: oop generics multiple-inheritance ada