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:58 Markus Schoepflin wrote: > 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? > And one more question, can I have a dispatching procedure that doesn't explicitly use the type it dispatches on? In C++, that would read: class foo { virtual void f() = 0; }; class bar { void f() { // Do something just depending on class type bar, // not on an object of the class, so the 'this' pointer // actually is never used. } }; Markus
From: Niklas Holsti on 20 Nov 2009 09:00 Markus Schoepflin wrote: > 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? Yes. You can do that either by Dmitry's method, declaring the parameter as FOO'Class, or by converting a FOO parameter to FOO'Class for the call. But note that if an operation has no parameters (and no return value) of type FOO (or access FOO), only of FOO'Class, it is not a primitive operation of FOO and cannot be overridden in derived types. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .
From: Dmitry A. Kazakov on 20 Nov 2009 09:10 On Fri, 20 Nov 2009 14:43:45 +0100, Markus Schoepflin wrote: > So If I understand this correctly, if I want dispatching to happen on a > given type, I always need to use the class type? Exactly. This helps both the compiler to make the program much more efficient by eliminating unnecessary dispatch and you indicating the design problems like this and making it safer in the opposite cases: Consider the case where one non-abstract operation calls another: type FOO is abstract tagged null record; procedure P (THIS : in out FOO); procedure A (THIS : in out FOO); .... procedure P (THIS : in FOO) is begin ... A (THIS); -- This is a part of the implementation of P for the type FOO ... end P; Here the call to A does not dispatch. In other language like C++ it would. Now consider a type derived from FOO, that overrides A, but inherits P. That could break the implementation of P in C++, but not in Ada, where P will behave exactly as it did before. When you design P you should decide whether it is a class-wide subprogram or not. That role of P will define the behavior of calls to A from its body. Sometimes the compiler can detect that the declared role of P does not match its implementation, as it was in your case. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
From: Niklas Holsti on 20 Nov 2009 09:10 > 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(a)see-the.signature wrote: > 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?) There is no way to call A on an object of (apparent) type FOO because A is declared as abstract for FOO. The compiler very correctly says that such a call is impossible. But you can call the overriding (concrete) implementation of A for the actual type of THIS (some non-abstract type derived from FOO) by converting to class-wide to force dispatching: A (FOO'Class (THIS)); > 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. There is no reason for such a warning because defining A in this way is legal and useful, as long as you convert the parameter to FOO'Class when you call it. You can consider the name A (of the abstract operation) a kind of place-holder for all the concrete implementations of A for derived types. But Dmitry probably thinks that there should be warning of the form "Bad design! Naughty!" :-) -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .
From: Niklas Holsti on 20 Nov 2009 09:19 Markus Schoepflin wrote: > Markus Schoepflin wrote: >> 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? >> > > And one more question, can I have a dispatching procedure that doesn't > explicitly use the type it dispatches on? No, as there is no implicit "this" parameter in Ada (and no syntactic brackets to group all the operations of a type). To make an operation overridable (a "primitive operation" in Ada terms) you have to include one or more parameters of the type (or of "access" to the type) or it must return a value of the type (or "access" to the type). And moreover the operation must be declared in the same package declaration as the type. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .
First
|
Prev
|
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 |