Ada中的动态调度与访问类型

时间:2016-03-09 17:28:22

标签: dynamic polymorphism ada

我正在尝试创建一个使用访问类型进行动态调度的包。我使用This Q/A作为指南,使用类类型实现了动态调度。

我不断收到一个编译错误:无法调用抽象子程序。这使我认为编译器要么不识别专用子程序,要么不将该类型识别为专用类型。但对我来说似乎都是正确的......我不明白。

main.2.ada

with Ada.Text_IO;
with Animal.Cat;

procedure Main is
    Tabby        : aliased Animal.Cat.Cat_t;
    Animal_Ref   : Animal.Any_Animal_Ptr := Tabby'Unchecked_Access;
    Result       : Boolean;
begin
    Animal.Stroke_Fur (Animal => Animal_Ref.all);

    Result := Animal.Is_Happy(Ptr => Animal_Ref);

    Ada.Text_IO.Put_Line ("Happy Animal = " & Boolean'Image (Result));

end Main;

animal.1.ada

package Animal is

    type base_t is abstract tagged limited null record;

    type Animal_t is abstract new 
        base_t with private;

    type Any_Animal_Ptr is access all Animal_t'Class;
    ----
    procedure Stroke_Fur (Animal : in out Animal_t) is abstract;
    ----
    function Is_Happy (Ptr : in Any_Animal_Ptr) return boolean is abstract;

private

    type Animal_t is abstract new base_t with 
    record
        Index : integer;
    end record;

end Animal;

animal.cat.1.ada

package Animal.Cat is

    type Cat_t is new Animal.Animal_t with private;
    type Cat_Ptr is access all Cat_t;

    ----
    procedure Stroke_Fur (Cat : in out Cat_t);
    ----
    function Is_Happy (Ptr : in Cat_Ptr) return Boolean;

private
    type Cat_t is new Animal.Animal_t with 
    record
        Purr : Boolean := False;
    end record;            

end Animal.Cat;

animal.cat.2.ada

package body Animal.Cat is

    ----
    procedure Stroke_Fur (Cat : in out Cat_t) is
    begin
        Cat.Purr := True;
    end Stroke_Fur;
    ----
    function Is_Happy (Ptr : in Cat_Ptr) return Boolean is
    begin
        return Ptr.Purr;
    end Is_Happy;

end Animal.Cat;

错误

main.2.ada:13:21:无法调用抽象子程序“Is_Happy”

1 个答案:

答案 0 :(得分:3)

function Is_Happy (Ptr : in Any_Animal_Ptr) return boolean is abstract;

不是Animal_t的原始操作(ARM3.2.3(2)),因此它不是调度;它只是一个抽象的子程序(因此无法调用)。

为什么要制作非调度子程序摘要?也许你可能有Metres类型,在这种情况下,预定义的”*”是不合适的(以米为单位的两个距离相乘会返回一个区域,而不是距离),你可能希望将其设为抽象以防止意外误用

无论如何,您可以使用访问

来声明Animal_t的基本操作
function Is_Happy (Ptr : access Animal_t) return boolean is abstract;

然后是猫

function Is_Happy (Ptr : access Cat_t) return Boolean;

(甚至

overriding
function Is_Happy (Ptr : access Cat_t) return Boolean;

如果您希望编译器检查它是否真的重写了。

顺便说一句,如果您使用的是Ada 2005或更高版本,则可以使用prefixed notation将呼叫写为

Animal_Ref.Stroke_Fur;
Result := Animal_Ref.Is_Happy;

更漂亮。