From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 109fba,2f84446733b06aca X-Google-Attributes: gid109fba,public X-Google-Thread: fac41,27502d015551c708,start X-Google-Attributes: gidfac41,public X-Google-Thread: 103376,2f84446733b06aca X-Google-Attributes: gid103376,public From: mheaney@ni.net (Matthew Heaney) Subject: Constructors for Ada (was: Converting C++ class to Ada) Date: 1996/12/12 Message-ID: #1/1 X-Deja-AN: 203866828 distribution: world references: <32ADF183.7195@lmtas.lmco.com> <58npck$iku$1@goanna.cs.rmit.edu.au> content-type: text/plain; charset=ISO-8859-1 organization: Estormza Software mime-version: 1.0 newsgroups: comp.lang.ada,comp.lang.c++,comp.lang.eiffel Date: 1996-12-12T00:00:00+00:00 List-Id: In article <58npck$iku$1@goanna.cs.rmit.edu.au>, Dale Stanbrough wrote: (1) What do I do about the constructor? As I understand C++, > I need to force the user to supply values for the components of > Object_Type when something of that type is declared. How do I do > this?" > >The only way to force this seems to be the use of private types with >discriminants. > > type Object_Type(<>) is private; > >which says this _may_ have discriminants, but that's private. > >The only way to initialize and object, and you are forced to, is >via a function. > > Item : Object_Type; -- illegal, must be initialized > > Item : Object_Type := Init(....); -- Ok. > >The full type definition does not have to have the discriminants. >IMHO, it would have been nicer to be able to say "this object must >be initialized when declared" by using a different mechanism to this >(rather obscure) one. Your solution is correct: call a function that returns a object of the type. Different functions can perform different kinds of initialization. But this only works if the type is non-limited (which is the normal case anyway). I'm not sure this technique - making the type indefinate to force initialization - qualifies as "obscure," though. Rather, it's just that we haven't all been programming in Ada 95 long enough for this to be an obvious idiom. However, you have touched on an area where I feel there is an omission in the language. The issue I have with the language is that there is an asymmetry between how stack objects are initialized and how heap objects are initialized. For example, to initialize an object on the heap: type Integer_Access is access Integer; O : Integer_Access := new Integer'(4); Why shouldn't I be able to do that for stack objects too? O : Integer'(4); What I'd like (and Dale too, it seems) is a way to initialize objects (on the stack or heap) by invoking a subprogram explicitly identified as a constructor, and be able to do so irrespective of whether the type is limited or non-limited. The problem is that in Ada initialization of an object on the stack requires assignment, but this not need be so. It's just a syntactic quirk that prevents me from calling an initialization subprogram during elaboration of a limited object. For example, suppose I had a persistant queue. I'd like to read its state from disk by doing this: Q : Queue'(Name => "my_queue.dat"); Though I suppose I could do that now if my queue were non-limited by using a function: Q : Queue := Create (Name => "my_queue.dat"); But suppose my type were limited. For example, I'd like to open a file during elaboration of the file object: F : File_Type'(Name => "my_file.dat", Mode => In_File); That's something I can't do now, because type File_Type is limited private. So I have to do this F : File_Type; begin Open (F, Name => "my_file.dat", Mode => In_File); I'd like to see a subprogram explicitly identified as a constructor: type T is limited private; constructor T (Name : in String; Mode : in File_Mode); or maybe constructor (Name : in String; Mode : in File_Mode) initializes T; But we can do better. Ian Joyner made the point in his C++ critique that it's often not obvious what each constructor does, because you only get the argument part of the signiture - there is no meaningful name. He points out that in Eiffel each constructor has a name, too, unlike C++. So maybe my hypothetical syntax is better if I can do this: constructor T Open (Name : in String; Mode : in File_Mode); or maybe constructor Open (Name : in String; Mode : in File_Mode) initializes T; Then we could use the name during initialization: F : File_Type'Open (Name => "my_file.dat", Mode => In_File); This feature is my current favorite for inclusion in a future version of the language. What do you think? -------------------------------------------------------------------- Matthew Heaney Software Development Consultant mheaney@ni.net (818) 985-1271