oop - Ada 中的私有原语的私有类型扩展和调度

我试图向用户隐藏库的某些方面并阅读 RM 进行类型转换,我不明白为什么以下代码会失败。

用户将实例化 root.child.concrete.concrete_t,然后将调用传递该实例的 root.p_userInterface,但在 root.adb 上引发编译错误:无效标记转换,与定义的类型“child_t'class”不兼容root-child.ads:4

根广告:

limited with root.child;

package root is

  procedure p_userInterface (obj : in out root.child.child_t'Class);

private

  type root_t is abstract tagged null record;

  procedure p_primitive (this : in out root_t) is abstract;

end root;

根.adb:

with root.child;

package body root is

  procedure p_userInterface (obj : in out root.child.child_t'Class) is
  begin
    -- error: invalid tagged conversion, not compatible with type "child_t'class" defined at root-child.ads:4
    root_t'Class(obj).p_primitive; 
  end p_userInterface;

end root;

根-child.ads:

package root.child is

  type child_t is abstract tagged private;

  function f_getComponent(this : in child_t) return Integer;

private

  type child_t is abstract new root_t with
    record
      component : Integer;
    end record;
  
  overriding
  procedure p_primitive (this : in out child_t) is abstract;

end root.child;

根-child.adb:

package body root.child is
  
  function f_getComponent(this : in child_t) return Integer is
  begin
    return this.component;
  end f_getComponent;

end root.child;

根子concrete.ads:

package root.child.concrete is

  type concrete_t is new child_t with private;

  procedure p_setAnotherComponent (this : in out concrete_t;
                                  c    : Boolean);

  function f_getAnotherComponent (this : concrete_t) return Boolean;

private

  type concrete_t is new child_t with
    record
      anotherComponent : Boolean;
    end record;
  
  overriding
  procedure p_primitive (this : in out concrete_t);

end root.child.concrete;

根子concrete.adb:

package body root.child.concrete is

  procedure p_primitive (this : in out concrete_t) is
  begin
    -- for example
    this.anotherComponent := True;
  end p_primitive;

  procedure p_setAnotherComponent (this : in out concrete_t;
                                   c    : Boolean) is
  begin
    this.anotherComponent := c;
  end p_setAnotherComponent;

  function f_getAnotherComponent (this : concrete_t) return Boolean is
  begin
    return this.anotherComponent;
  end f_getAnotherComponent;


end root.child.concrete;

为什么?我了解 root 的实现无法看到其 root.child 子包的私有部分,因此无法看到类型 child_t 正在私下扩展 root_t。我说的对吗?

我能以不同的方式实现类似的目标吗?我想将 p_primitive 隐藏给用户,因为它是为了执行内部操作,但如果可能的话,我想在内部调度它。

回答1

我想我终于实现了。这是对我有用的解决方案,仅适用于更改的单位,注释掉旧部分,因为我不能使用 html 罢工标签来划掉代码:

根广告:

--limited with root.child;

package root is

  type root_t is abstract tagged null record;

  procedure p_userInterface (obj : in out root_t'Class); --root.child.child_t'Class);

private

  --type root_t is abstract tagged null record;

  --procedure p_primitive (this : in out root_t) is abstract;

  type hiddenRoot_t is abstract new root_t with null record;

  procedure p_primitive (this : in out hiddenRoot_t) is abstract;

end root;

根.adb:

--with root.child; It was not needed before neither

package body root is

  procedure p_userInterface (obj : in out root_t'Class) is --root.child.child_t'Class) is
  begin
    --root_t'Class(obj).p_primitive; -- invalid tagged conversion, not compatible with type "child_t'class"

    hiddenRoot_t'Class(obj).p_primitive;

  end p_userInterface;

end root;

根-child.ads:

package root.child is

  --type child_t is abstract tagged private;
  type child_t is abstract new root_t with private;

  function f_getComponent(this : in child_t) return Integer;

private

  --type child_t is abstract new root_t with
  type child_t is abstract new hiddenRoot_t with
    record
      component : Integer;
    end record;
  
  overriding
  procedure p_primitive (this : in out child_t) is abstract;

end root.child;

这样我就可以私下分派到concrete_t 类型的p_primitive 的实现,并且在main 上我可以确保concrete_t 的实例没有p_primitive 的可见性。对此解决方案的任何进一步评论将不胜感激,我不知道我是否遗漏了一些重要的东西,但似乎有效。我不知道这是否是正确的解决方案。

相似文章

task - 任务:非常缓慢的响应

我的实际程序创建了一个task,我不会对控制消息做出应有的反应。由于它已经变得相当大,我提出了一个具有相同控制逻辑的简短测试程序。它创建了一个背景task,它每0.1秒重复一个循环。根据受保护的标志“...