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.
next prev 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