具有访问类型的 Ada 中的动态调度
Dynamic Dispatching in Ada with Access Types
我正在尝试创建一个使用访问类型进行动态调度的包。我已经使用 Class 类型实现了动态调度,使用 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;
动物.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"
function Is_Happy (Ptr : in Any_Animal_Ptr) return boolean is abstract;
不是 Animal_t
的原始操作 (ARM3.2.3(2)),因此它不是调度;它只是一个抽象的子程序(因此不能被调用)。
为什么要将非调度子程序抽象化?也许你可能有一个类型 Metres
,在这种情况下,预定义的 ”*”
是不合适的(将两个以米为单位的距离 returns 乘以一个区域,而不是距离)并且你可能希望将其抽象化以防止无意中误用。
无论如何,您可以使用访问方式声明 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;
哪个更漂亮
我正在尝试创建一个使用访问类型进行动态调度的包。我已经使用 Class 类型实现了动态调度,使用 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;
动物.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"
function Is_Happy (Ptr : in Any_Animal_Ptr) return boolean is abstract;
不是 Animal_t
的原始操作 (ARM3.2.3(2)),因此它不是调度;它只是一个抽象的子程序(因此不能被调用)。
为什么要将非调度子程序抽象化?也许你可能有一个类型 Metres
,在这种情况下,预定义的 ”*”
是不合适的(将两个以米为单位的距离 returns 乘以一个区域,而不是距离)并且你可能希望将其抽象化以防止无意中误用。
无论如何,您可以使用访问方式声明 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;
哪个更漂亮