我想知道如何从 ADA 中的父类调用重写的方法。让我们考虑以下示例。一个 Parent
类有一些被 Child
覆盖的方法类(class)。 Parent
中有一个方法类(即 Prints
)调用它的一些重写方法。但是不会调用被覆盖的方法!这是示例:
--- parent ---
package Parents is
type Parent is tagged null record;
procedure Prints(Self: in out Parent);
-- these will be overridden
procedure Print1(Self: in out Parent) is null;
procedure Print2(Self: in out Parent) is null;
end Parents;
...
package body Parents is
procedure Prints(Self: in out Parent) is
begin
Put_Line("Parents.Prints: calling prints...");
Self.Print1;
Self.Print2;
end;
end Parents;
--- child ---
With Parents;
package Childs is
type Child is new Parents.Parent with null record;
overriding procedure Print1(Self: in out Child);
overriding procedure Print2(Self: in out Child);
end Childs;
...
package body Childs is
procedure Print1(Self: in out Child) is
begin
Put_Line("Child.Print1 is printing...");
end;
procedure Print2(Self: in out Child) is
begin
Put_Line("Child.Print2 is printing...");
end;
end Childs;
--- 主要 ---
procedure Main is
anyprint : access Parents.Parent'Class;
begin
anyprint := new Childs.Child;
anyprint.Prints;
end Main;
问题
我期望看到的是对这两个
Print1
的调度调用和 Print2
来自 Child
.但是不会调用被覆盖的方法!有 C++ 背景,这种类型的多态调用对我来说很有意义,但我不知道 Ada 是如何对待它们的?是调用
Self.Print1;
来自 Prints
错误的?
最佳答案
在 Ada 中,仅当对象是类范围的类型时才会发生分派(dispatch)。相关手册部分为 ARM 3.9.2 .
在 Parents.Prints
, 控制操作数 Self
是 Parent
类型,并且是“静态标记的”,因此没有调度。
一种方法是使用“重新调度”,如下所示:
procedure Prints(Self: in out Parent) is
begin
Put_Line("Parents.Prints: calling prints...");
Parent'Class (Self).Print1;
Parent'Class (Self).Print2;
end;
其中 View 转换
Parent'Class (Self)
表示 .Print1
所在的对象被调用是“动态标记的”并且调用调度。如你所愿,
Prints
能够在派生类型中被覆盖。这并不总是(甚至通常?)你想要的。如果不是,将其参数更改为类范围是合适的:procedure Prints(Self: in out Parent'Class);
(当然还有 body !)然后一切都按您的预期进行。
[附注:我现在了解到 object.operation 表示法适用于类范围的对象!]
关于oop - 从 Ada 中的基类调用重写的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28480964/