Christoph Karl Walter Grein
A noble principle of sound software engineering is information hiding. It requests to hide everything beyond the programmer's need to know. Also Lady Ada loves to be secretive; she is a perfect mystery-monger.
with Ada.Finalization; use Ada.Finalization; package Mystery_Monger is type Root is tagged private; private type Root is new Controlled with null record; procedure Initialize (Obj: in out Root); procedure Adjust (Obj: in out Root); procedure Finalize (Obj: in out Root); end Mystery_Monger;
package Mystery_Monger.Derived is type Something is tagged private; Nothing: constant Something; private type Something is new Root with null record; procedure Initialize (Obj: in out Something); procedure Adjust (Obj: in out Something); procedure Finalize (Obj: in out Something); Nothing: constant Something := (Root with null record); end Mystery_Monger.Derived;
By derivation from the predefined type Ada.Finalization.Controlled, a class of controlled types is declared arising from the ancestor type Root. Controlledness is a new Ada95 feature giving us additional control over the three fundamental operations on objects: creation, assignment, destruction - associated to the three procedures Initialize, Adjust and Finalize. The exact definition can be found in the Ada RM chapter 7.6 User-Defined Assignment and Finalization. We will look at the behaviour of controlled types with the following simple main program:
with Mystery_Monger.Derived; use Mystery_Monger.Derived; with Ada.Text_IO; use Ada.Text_IO; procedure Try_It is Thing: Something; begin Put_Line ("Body of Try_It begins now."); Thing := Nothing; Put_Line ("Body of Try_It ends now."); end Try_It;
Here essentially the following happens:
Let us summarize the sequence of events:
Initialize called for object of type Root | » | Initialization of Root part of Nothing |
Initialize called for object of type Something | » | Initialization of the local variable Thing |
Body of Try_It begins now. | ||
Finalize called for object of type Something | » | Pre-assignment finalization of Thing |
Adjust called for object of type Something | » | Post-assignment adjustment of Thing |
Body of Try_It ends now. | ||
Finalize called for object of type Something | » | End of scope of Thing |
Finalize called for object of type Something | » | End of scope of Nothing |
The other day, Lady Ada received a desperate letter from one of her newer admirers. He sent her a little programm he had written, and wrote:
with Mystery_Monger; use Mystery_Monger; package Greenhorn is type Something is tagged private; Nothing: constant Something; private type Something is new Root with null record; procedure Initialize (Obj: in out Something); procedure Adjust (Obj: in out Something); procedure Finalize (Obj: in out Something); Nothing: constant Something := (Root with null record); end Greenhorn;
with Greenhorn; use Greenhorn; with Ada.Text_IO; use Ada.Text_IO; procedure Surprise is Thing: Something; begin Put_Line ("Body of Surprise begins now."); Thing := Nothing; Put_Line ("Body of Surprise ends now."); end Surprise;
"Dear Lady Ada,
as you can see from the attachment, I have done exactly the same as you, however with a result that is totally unexpected for me, unexperienced disciple that I am - it is true, it is similar to the above, however none of the three operations for Something are called, instead always those for Root. Why?
Begging for enlightenment I remain your most obedient servant, ..."
A compilable and executable (German) program version can be downloaded here.
© Copyright 2000 C.K.W. Grein |