comp.lang.ada
 help / color / mirror / Atom feed
From: "Robert I. Eachus" <rieachus@comcast.net>
Subject: Re: Question about OO programming in Ada
Date: Thu, 27 Nov 2003 17:12:21 -0500
Date: 2003-11-27T17:12:21-05:00	[thread overview]
Message-ID: <aLKdnQBplLla61uiRVn-sQ@comcast.com> (raw)
In-Reply-To: <bq3mef$49e$1@online.de>

Ekkehard Morgenstern wrote:

> But I have a few more questions, so it'd be great if you could answer them.
> :-)

Ludovic Brenta and Jeffery Carter did a pretty good job of that, but 
there were a couple comments I wanted to add.

> This is really a great feature! So I can practically test if any object is a
> member of a particular class, or set of classes?

As answered elsewhere, actually a set of types, which is what a class is 
in Ada.  But you can do more than that.  You can test for membership in 
any subtype.  The canonical example is "if Today in Weekday..."  where 
Weekday is declared as "subtype Weekday is Day range Monday..Friday;" or 
if necessary for some reason you could check for membership in a range:
"if Today in Monday..Wednesday..."

Again, in Ada you choose the most appropriate way to communicate the 
meaning of the code to the reader, and let the compiler figure out how 
to do what you want.

> I still wonder if The_Registration is actually a reference, or is it the
> object returned by Register()?

Don't wonder, this is information hiding at work.  You expect the 
implementor of the Registration type to export an abstract data type 
(ADT) and operations on it that match your expectations, and the 
documentation.  Whether a Registration is an access type, a record type, 
a controlled record type or even an object of type 
Ada.Strings.Unbounded.Unbounded_String should not matter to any user of 
the package.

This turns out to be another way of saying that Ada allows you to 
enforce that any code outside the declaring package (and possibly child 
packages) that depends on how Registration is represented is a bug.  So 
if you need to change the representation later, the changes are all 
localized.

> I.e. if I wanted only a reference to the object, would I have to use an
> access to Registration'Class?

See above.  The package might export a reference type to be used in 
implementations of other data structures.  But again, what is usually 
exported in Ada is the reference SEMANTICS.  Whether the ADT 
Registration_Ref is a registration number, an access type, or an index 
into a database need not be revealed to the user. It is just a way to 
refer to a Registration.  In Ada, the expectation is that you hide as 
much information as possible.  This makes development, debugging, and 
support of the application much easier.

> Can I return an object of type Node'Class, or do I have to return an access
> to it?

You can do either.  But the usual is to return an object of generic 
formal type Node, then the actual can be whatever you want, including 
Registration'Class.

> But what about return values from functions? Or does the return value in a
> function correspond to an "out" parameter in a procedure?

No, but the difference is pretty subtle.  A function can return an 
object of an unconstrained subtype, or classwide type, and the function 
itself will determine what to return.  In the case of an out procedure 
parameter, any constraints on the object are determined by the caller.

So if a function returns a String, the size of the String (technically 
its bounds) can be determined by the inside the function:

function Weird(X, Y: Integer) return String is
begin return Integer'Image(X*(Y/GCD(X,Y)); end Weird;

With an out parameter, the procedure can access the attributes of the 
object passed by the caller:

procedure Blank(S: out String) is
begin S := (others => ' '); end Blank;

Of course you can explicitly pass attribute values to a string:

function Blank(S: in Positive) return String is
begin return String'(1..S => ' '); end Blank;

X: String(1..Length) := Blank(Length);

> BTW, how do I use the Finalization package? I'd like to use things like
> constructors and destructors sometimes to be able to initialize / cleanup
> objects when they're created or destroyed.

Good idea.  But the real answer to your question is that you should only 
use controlled types directly with more experience.  Otherwise use an 
existing data structure library to do things.  (Or if necessary modify 
existing code to do what you need.)  Getting the "corner cases" of 
memory management is tricky irrespective of the language used, so using 
a well tested package means you won't have to track down very subtle 
memory leaks.  (The usual problem cases are when an exception occurs 
during the creation or freeing of a data structure.)

> I'm really surprised how short my source code has become. It's just the way
> programming's meant to be that I can concentrate on the key tasks at hand.
> :-)

Exactly.  Programming in Ada should be just as hard as getting the 
algorithms right--and no harder.

> What I also find very useful is the renaming of packages / procedures etc.
> Does that have any impact on dispatching or inheritance (in the case of
> renaming procedures)?

Not that you should worry about.  There are again subtle cases where 
renaming will cause static dispatching to replace dynamic dispatching, 
or where renaming makes it easier for the compiler to generate good 
code.  But in general use renaming when it makes your work easier, and 
expect the semantic analysis phase of the compiler to eliminate any 
potential overhead.  I often use renaming to give more meaningful names 
to operations and data types in generic instances.

> BTW, can I instantiate a generic package in a procedure body (initialized
> with a value passed as a parameter)? (I didn't try yet)

Yes you can.  There are some cases involving static nesting levels that 
can cause problems.  For example, packages that create controlled types 
need to be instantiated at library level, either in package 
specifications or bodies.

If you run into a case where this is a problem, the solution is to make 
the procedure a generic procedure, then pass the actual controlled type 
as a generic formal type parameter.

This leads to one of the most powerful aspects of Ada generics:  Generic 
instantiation occurs at run-time, not at compile time.  So it is 
perfectly legitimate to instantiate a generic inside a loop, and expect 
each instance to be different.  (Or more to the point, similar to the 
previous instance only by happenstance.)

Note that for a generic subprogram, there are three or more "freezing" 
points where actuals are matched to formals.  (These are different from 
freezing points in Ada for aspects of a type.)  The first occurs at 
compile time, the second occurs when, at run-time, the generic 
specification is elaborated, and the third occurs when the instance is 
called.  Why "or more"?  A generic package may contain other generic 
declarations, creating a cascade of such parameter freezing points. This 
can be a very powerful tool if used right.

> The problem with arrays is that they need to be preallocated to a particular
> size, which can consume a lot of memory. Lists and Nodes occupy only the
> memory that they actually use.

In Ada it is trickier than that. ;-)  Ada array sizes can be 
dynamic--determined at run-time--and still be the exact size needed.  Or 
you can use data structures like doubling lists.  In a doubling list 
every time it gets full, you allocate a new array twice the size, and 
copy all the current data over.  For a list that only grows, such a 
structure never takes as much as twice the space needed, and the "extra" 
copying averages to between one and two copies per entry.

Or another structure I have used for sparse array implementation.  You 
manage a pool of nodes all allocated from the same heap, but instead of 
allocating one at a time, you allocate an array of 1000 or so.  Since 
you never try to return a part of one of these allocated chunks, it 
minimizes the allocation and freeing overhead.

Note again what makes all this possible in Ada.  The chunk management 
layer was hidden from the sparse matrix implementation, the sparse 
matrix implementation was hidding from the algorithms that used it.  So 
instead of making the overall coding job impossibly complex, I had three 
separate sections of code, all of which were just as complex as they 
needed to be.  I could test the algorithms using a non-sparse matrix 
package, and test the sparse matrix software with an implementation that 
allocated nodes individually.  Then when all the code was complete and 
tested, I could combine it and get the real-time performance that I needed.

> How do I avoid casting access types between derived classes?

By declaring the access type as "access all Foo'Class;" if that is what 
it should be.  Again, if you find yourself writing type conversions 
outside very special circumstances it indicates that you haven't thought 
the design through correctly.  Of course, sometimes you need to convert 
floating-point values to fixed-point or integer, or vice-versa.  And in 
the bodies of operations on derived types you may want to call the 
parent operation, but as I said, there are a few contexts where type 
conversions are expected.

Oh, and note that in Ada, class trees tend to be "bushier."  In the 
Registration example, there might be one parent Registration type and 
all other members of the class would be derived from it directly.  There 
are some cases involving mix-ins where you have a sequence of 
derivations, but usually only the ultimate parent and child are visible 
outside the defining package.

> Yes, but you don't really need to know about all these things to program in
> Ada, and that's really a good thing. You can get along well with basic
> constructs, and the more intricate details of the language can be postponed
> to be used later when necessary.

Exactly, and it was intended that way.  There are two subsets of Ada 
that people learn, the "Pascal superset," everything needed to write 
Pascal programs in Ada, and then the "Ada subset," basically the Pascal 
superset plus packages, attributes, generic instantiations, and 
exceptions.  Then the other separable parts of Ada, OO, programming in 
the large, tasking, writing generic units, etc. can be learned in any order.

> I hope I can get back to you with my questions when I have to write an Ada
> compiler and run-time system.

You have already been warned.  Don't.  Porting GNAT or some other 
existing Ada compiler will save you a huge amount of grief.  A usable 
Ada compiler required about a man-decade of work back in the Ada 83 
days.  By now GNAT, Ada Magic, Rational, and so on would take several 
man-centuries to duplicate.  The front-end, semantic analysis, and 
machine independent optimization phases are each several times the size 
of the code generator, and if you port an existing code generator, you 
will find that the tools are designed to support just that.

-- 
                                           Robert I. Eachus

100% Ada, no bugs--the only way to create software.




  parent reply	other threads:[~2003-11-27 22:12 UTC|newest]

Thread overview: 109+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-11-25 19:04 Question about OO programming in Ada Ekkehard Morgenstern
2003-11-25 20:17 ` Randy Brukardt
2003-11-26  0:34   ` Ekkehard Morgenstern
2003-11-26  6:17     ` Vinzent 'Gadget' Hoefler
2003-11-26  9:29     ` Dmitry A. Kazakov
2003-11-26 15:54     ` Stephen Leake
2003-11-26 20:07       ` Randy Brukardt
2003-11-26 21:36         ` Stephen Leake
2003-11-26  8:56   ` Peter Hermann
2003-11-25 20:55 ` Martin Krischik
2003-11-26  0:22   ` Ekkehard Morgenstern
2003-11-26  1:00     ` Jeffrey Carter
2003-11-26 16:36     ` Martin Krischik
2003-11-26 18:09       ` Robert I. Eachus
2003-11-27 13:45         ` Jean-Pierre Rosen
2003-11-25 21:48 ` Stephen Leake
2003-11-26  0:01   ` Ekkehard Morgenstern
2003-11-26  1:16     ` Jeffrey Carter
2003-11-26 15:10     ` Georg Bauhaus
2003-11-26 15:48     ` Stephen Leake
2003-11-26 16:24       ` Hyman Rosen
2003-11-26 17:58     ` Robert I. Eachus
2003-11-27  2:10       ` Ekkehard Morgenstern
2003-11-27 10:15         ` Ludovic Brenta
2003-11-27 18:35         ` Jeffrey Carter
2003-11-28  4:35           ` Hyman Rosen
2003-11-28  7:28             ` Vinzent 'Gadget' Hoefler
2003-11-28  8:46               ` Dale Stanbrough
2003-11-28 10:16                 ` Vinzent 'Gadget' Hoefler
2003-12-01 15:57             ` Martin Krischik
2003-12-01 16:47               ` Hyman Rosen
2003-12-03 18:35                 ` Martin Krischik
2003-12-01 21:13               ` Jeffrey Carter
2003-12-02  8:47               ` Dmitry A. Kazakov
2003-12-03  9:29                 ` Pascal Obry
2003-12-03 11:26                   ` Dmitry A. Kazakov
2003-12-03 12:49                     ` Ludovic Brenta
2003-12-03 13:41                       ` Dmitry A. Kazakov
2003-12-03 14:11                         ` Ludovic Brenta
2003-12-03 14:45                           ` Dmitry A. Kazakov
2003-12-03 15:44                         ` Hyman Rosen
2003-12-03 16:11                           ` Dmitry A. Kazakov
2003-12-03 18:20                           ` David C. Hoos
     [not found]                           ` <28eb01c3b9ca$25b18870$b101a8c0@sy.com>
2003-12-03 18:35                             ` Hyman Rosen
2003-12-03 20:05                           ` Randy Brukardt
2003-12-03 20:57                             ` Hyman Rosen
2003-12-03 21:16                               ` Hyman Rosen
2003-12-03 22:04                           ` Pascal Obry
2003-12-03 22:34                             ` Hyman Rosen
2003-12-04  1:23                               ` Robert I. Eachus
2003-12-04  7:15                                 ` Hyman Rosen
2003-12-04 17:43                                   ` Warren W. Gay VE3WWG
2003-12-04  8:55                                 ` Dmitry A. Kazakov
2003-12-04 19:13                                   ` Randy Brukardt
2003-12-04 19:29                                     ` Hyman Rosen
2003-12-04 21:32                                   ` Robert I. Eachus
2003-12-05  8:43                                     ` Dmitry A. Kazakov
2003-11-27 22:12         ` Robert I. Eachus [this message]
2003-11-28  6:37           ` Simon Wright
2003-11-30  2:51             ` Robert I. Eachus
2003-12-06  7:48 ` Chad Bremmon
2003-12-06 13:33   ` Jeff C,
2003-12-06 22:44   ` Hyman Rosen
2003-12-07  3:02     ` Chad Bremmon
2003-12-07  7:53       ` Hyman Rosen
2003-12-07 15:34         ` James Rogers
2003-12-07 18:30           ` Martin Krischik
2003-12-07 20:25             ` James Rogers
2003-12-08  3:36               ` Hyman Rosen
2003-12-08  4:42                 ` Chad Bremmon
2003-12-08  8:42                   ` Hyman Rosen
2003-12-08  9:34                     ` Dmitry A. Kazakov
2003-12-08 13:25                       ` Hyman Rosen
2003-12-08 15:05                         ` Dmitry A. Kazakov
2003-12-09  4:38                           ` Hyman Rosen
2003-12-09  8:19                             ` Dmitry A. Kazakov
2003-12-09 13:29                               ` Hyman Rosen
2003-12-09 14:36                                 ` Dmitry A. Kazakov
2003-12-09 15:05                                   ` Hyman Rosen
2003-12-09 15:59                                     ` Dmitry A. Kazakov
2003-12-09 16:41                                       ` Hyman Rosen
2003-12-10 11:32                                         ` Dmitry A. Kazakov
2003-12-10 15:27                                           ` Hyman Rosen
2003-12-10 17:15                                             ` Dmitry A. Kazakov
2003-12-08 17:55                       ` Chad Bremmon
2003-12-08 23:09                         ` Hyman Rosen
2003-12-09  8:26                         ` Dmitry A. Kazakov
2003-12-08 19:33                       ` Martin Krischik
2003-12-09  4:41                         ` Hyman Rosen
2003-12-08 17:27                     ` Chad Bremmon
2003-12-08 18:44                       ` Georg Bauhaus
2003-12-08 19:27                         ` Martin Krischik
2003-12-08 19:36                         ` Chad Bremmon
2003-12-09  4:43                           ` Hyman Rosen
2003-12-08 23:23                       ` Hyman Rosen
2003-12-08 19:25                     ` Martin Krischik
2003-12-07 21:29           ` Peter C. Chapin
2003-12-08  3:44             ` Hyman Rosen
2003-12-08  3:46           ` Hyman Rosen
2003-12-08  5:54             ` James Rogers
2003-12-08  8:45               ` Hyman Rosen
2003-12-07 17:39         ` Chad Bremmon
2003-12-08 23:39           ` Hyman Rosen
2003-12-09  2:36             ` Chad Bremmon
2003-12-09  4:52               ` Hyman Rosen
2003-12-09 11:24               ` Georg Bauhaus
2003-12-09 18:42                 ` Chad Bremmon
2003-12-09 20:11                   ` Hyman Rosen
2003-12-08 23:40           ` Hyman Rosen
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox