From: Markus Schoepflin on
Hello,

I'm trying to fell may way around object oriented Ada programming, and I
think I must be missing something absolutely basic. Please consider the
following package:

---%<---
package FOOS is

type FOO is abstract tagged null record;

procedure P (THIS : in FOO);
procedure A (THIS : in FOO) is abstract;

end FOOS;

package body FOOS is

procedure P (THIS : in FOO)
is
begin
A (THIS);
end;

end FOOS;
--->%---

When trying to compile this, I get:

foos.adb:6:07: call to abstract function must be dispatching
gnatmake: "foos.adb" compilation error

What is the compiler trying to tell me here? And how do I go about calling
abstract procedures?

TIA,
Markus
From: Dmitry A. Kazakov on
On Fri, 20 Nov 2009 14:15:33 +0100, Markus Schoepflin wrote:

> I'm trying to fell may way around object oriented Ada programming, and I
> think I must be missing something absolutely basic.

> Please consider the following package:
>
> ---%<---
> package FOOS is
>
> type FOO is abstract tagged null record;
>
> procedure P (THIS : in FOO);
> procedure A (THIS : in FOO) is abstract;
>
> end FOOS;
>
> package body FOOS is
>
> procedure P (THIS : in FOO)
> is
> begin
> A (THIS);
> end;
>
> end FOOS;
> --->%---
>
> When trying to compile this, I get:
>
> foos.adb:6:07: call to abstract function must be dispatching
> gnatmake: "foos.adb" compilation error
>
> What is the compiler trying to tell me here? And how do I go about calling
> abstract procedures?

It tells you that the type of THIS is FOO, so you cannot call to A, because
A is not defined on FOO.

If P is to be defined in terms of any type from the class FOO, then P has
to be declared differently (class-wide):

package FOOS is
type FOO is abstract tagged null record;
procedure P (THIS : in FOO'Class);
-- I am SAME for the whole class rooted in FOO
procedure A (THIS : in FOO) is abstract;
-- I have an implementation in each instance of the class except
-- for the abstract ones like FOO.
end FOOS;

package body FOOS is
procedure P (THIS : in FOO'Class) is
begin
A (THIS);
-- I do not know what kind of FOO is THIS. So I
-- dispatch to A according to the tag of THIS.
end P;
end FOOS;

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: stefan-lucks on
If Foo is a tagged type, then
"procedure A(This: [in] [out] Foo)"

expects *exactly* the same type as the actual parameter. If you want
"either type Foo or any of its object-oriented children" you write

"procedure B(This: [in] [out] Foo'Class)".

In your case, Foo is an abstract tagged type. As much as I seem to
understand Ada, there is no way to actually call procedure A -- because
you can't have any actuals of an abstract type. (Hey you guys out there,
am I wrong?)

If I am right, it is very regrettable that the compiler doesn't issue a
warning when compiling "procedure A(This: [in] [out] Foo)" for an abstract
type Foo ... perhaps better, a revised Ada should prohibit that.

So long

Stefan


On Fri, 20 Nov 2009, Markus Schoepflin wrote:


> ---%<---
> package FOOS is
>
> type FOO is abstract tagged null record;
>
> procedure P (THIS : in FOO);

-------> replace by
procedure P (THIS : in FOO'Class);

> procedure A (THIS : in FOO) is abstract;
>
> end FOOS;
>
> package body FOOS is
>
> procedure P (THIS : in FOO)

-------> replace by
procedure P (THIS : in FOO'Class);

> is
> begin
> A (THIS);
> end;
>
> end FOOS;
> --->%---
>
> When trying to compile this, I get:
>
> foos.adb:6:07: call to abstract function must be dispatching
> gnatmake: "foos.adb" compilation error
>
> What is the compiler trying to tell me here? And how do I go about calling
> abstract procedures?
>
> TIA,
> Markus
>

--
------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------
Stefan dot Lucks at uni minus weimar dot de
------ I love the taste of Cryptanalysis in the morning! ------

From: Markus Schoepflin on
Dmitry A. Kazakov wrote:

[...]

Thanks for you swift and helpful reply.

> If P is to be defined in terms of any type from the class FOO, then P has
> to be declared differently (class-wide):

So If I understand this correctly, if I want dispatching to happen on a
given type, I always need to use the class type?

Regards,
Markus
From: Niklas Holsti on
Markus Schoepflin wrote:
> Hello,
>
> I'm trying to fell may way around object oriented Ada programming, and I
> think I must be missing something absolutely basic. Please consider the
> following package:
>
> ---%<---
> package FOOS is
>
> type FOO is abstract tagged null record;
>
> procedure P (THIS : in FOO);
> procedure A (THIS : in FOO) is abstract;
>
> end FOOS;

No problems there (well, Dmitry will have philosophical objections to
this design :-)

> package body FOOS is
>
> procedure P (THIS : in FOO)
> is
> begin
> A (THIS);

At this point, the compiler knows that THIS is a FOO object, or is to be
seen as a FOO object. But you have said that the procedure A on FOO is
abstract -- not implemented -- so you cannot call it.

I assume that your intention is to call the procedure A that is
implemented (overriden) for the actual object THIS, which is of some
type derived from FOO .. some type in FOO'Class for which you have
implemented A. To do so, you must ask the compiler to make this call
dispatching, by converting the parameter to FOO'Class:

A (FOO'Class (THIS));

This is called a "redispatching" call, because the procedure P may have
been reached as the result of a dispatching call on P, and now we are
asking to dispatch again.

One way to understand this is that in Ada by default calls are
statically bound, not run-time bound (dispatching). Only calls that have
parameters of class type are dispatching.

Dmitry has philosophical objections to redispatching, which is why he
suggests that you should declare P with a class-type parameter THIS in
the first place, so that A (THIS) will dispatch. Either will work, but
in Dmitry's approach you cannot override P for derived types, because it
is then a class-wide operation, not a primitive operation of FOO. In
both approaches you can override A for derived types (and you must
override it because it is abstract in FOO).

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .