Reputation: 102
I have a reasonable amount of experience with Ada, but I have never used objects before. I found I had to use them to avoid the complications of not null access discriminate record types with task safe data structures. I need to make a function that takes in a base class and based on an if statement do dynamic dispatching, but I get an "incompatible types" error if the type I am testing is not in the class in the conditional. Is what I want to do impossible in Ada?
with Ada.Text_IO; use Ada.Text_IO;
procedure Dispatch is
type foo is tagged record
bar : boolean;
end record;
type foo2 is new foo with record
bar2 : boolean;
end record;
type foo3 is new foo with record
bar3 : boolean;
end record;
f3 : foo3;
procedure Do_Something(fubar : in out foo'class) is
begin
if fubar in foo2'class then
fubar.bar2 := True;
end if;
end Do_Something;
begin
Do_Something(f3);
end Dispatch;
Upvotes: 1
Views: 243
Reputation: 25511
Here, your code fails to compile with dispatch.adb:16:15: no selector “bar2" for type “foo'class" defined at line 3
; nothing about incompatible types.
Anyway, the problem with the code as posted is that there is no component bar2
in foo
; the only components visible in an object through a view of type foo’class
are those in an object of type foo
.
To get round this, you can change the view of fubar
to foo2
:
if fubar in foo2'class then
foo2 (fubar).bar2 := true;
end if;
However, this is not dispatching! To get a dispatching call you need
and you need a more complicated example, because you can only declare primitive operations in a package spec. Something like
package Dispatch is
type Foo is tagged record
Bar : Boolean;
end record;
procedure Update (F : in out Foo; B : Boolean) is null; -- primitive
type Foo2 is new Foo with record
Bar2 : Boolean;
end record;
overriding procedure Update (F : in out Foo2; B : Boolean);
type Foo3 is new Foo with record
Bar3 : Boolean;
end record; -- inherits default Update
end Dispatch;
package body Dispatch is
procedure Update (F : in out Foo2; B : Boolean) is
begin
F.Bar2 := B;
end Update;
end Dispatch;
procedure Dispatch.Main is
F3 : Foo3;
procedure Do_Something(Fubar : in out Foo'Class) is
begin
Fubar.Update (True); -- dispatches
end Do_Something;
begin
Do_Something(F3);
end Dispatch.Main;
Upvotes: 3