ADA 中的多类型继承通过通用混合

Multiple type inheritance in ADA via generic mixins

为了减少测试和重复代码,我发现了通过泛型混合实现的多重继承,但我不知道如何实现这一目标的最佳方法以及最佳实践。

具有以下 class 层次结构示例(用 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 class 上定义的方法,但是,当我尝试使用通用方法时,我得到的是:

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;

为什么?因为我封装了泛型包实例化? 那么,如何解决才是最好的呢?在子 classes 中创建 public 方法并在方法实现中调用私有泛型实例化方法?因为我想将通用实例化保持为私有。通过这样做,我能够设置和获取泛型的属性。

这些是对 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;

欢迎提出任何建议and/or最佳实践。

no selector "P_SetGenericAttribute" for private type "Child1_T" ...

您收到此错误的原因是您的实现(GenericChild 实例化的派生)是私有的;您的客户根本看不到类型 这样的推导。


但是你有一个更大的问题:Ada 不像你的图那样进行多重继承。不过,您可以执行多个 interface 类型并从中派生。 OR 你可以使用 generic 和静态多态性。 -- 但是直接的多重继承是行不通的。 (您可以,正如您提到的,也可以使用混合,但这些并不是真正的继承。)