Prev: Operation can be dispatching in only one type
Next: Genode implements zero-footprint runtime for Ada and SPARK
From: Markus Schoepflin on 20 Nov 2009 08:15 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 20 Nov 2009 08:27 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 20 Nov 2009 04:31 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 20 Nov 2009 08:43 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 20 Nov 2009 08:56 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 . @ .
|
Next
|
Last
Pages: 1 2 3 4 Prev: Operation can be dispatching in only one type Next: Genode implements zero-footprint runtime for Ada and SPARK |