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.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,436e4ce138981b82 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2004-03-11 05:55:52 PST Path: archiver1.google.com!news2.google.com!news.maxwell.syr.edu!newsfeed.mathworks.com!nntp.abs.net!ash.uu.net!spool.news.uu.net!not-for-mail Date: Thu, 11 Mar 2004 08:55:23 -0500 From: Hyman Rosen User-Agent: Mozilla Thunderbird 0.5 (Windows/20040207) X-Accept-Language: en-us, en MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: abstract sub programs overriding References: <1078776213.376775@master.nyc.kbcfp.com> <1078839257.157439@master.nyc.kbcfp.com> <5cmr40t76va200betf07b7bd6er05ltto9@4ax.com> <1078845298.702789@master.nyc.kbcfp.com> <0ipr40thtf86b520a0qdi003aj87gtuhd4@4ax.com> <1078849973.701176@master.nyc.kbcfp.com> <1078924150.268074@master.nyc.kbcfp.com> <1078934469.744922@master.nyc.kbcfp.com> <1078949096.760629@master.nyc.kbcfp.com> In-Reply-To: Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Organization: KBC Financial Products Message-ID: <1079013337.572283@master.nyc.kbcfp.com> Cache-Post-Path: master.nyc.kbcfp.com!unknown@aphelion.nyc.kbcfp.com X-Cache: nntpcache 3.0.1 (see http://www.nntpcache.org/) NNTP-Posting-Host: 204.253.250.10 X-Trace: 1079013337 9344 204.253.250.10 Xref: archiver1.google.com comp.lang.ada:6234 Date: 2004-03-11T08:55:23-05:00 List-Id: Robert I. Eachus wrote: > No, he is right. We'll get to that below. > No, as I said, there are two common idioms, the first is to call the > parent Initialize AFTER doing any initialization work needed on the > fields that occur only in the child. > > procedure Initalize(Object: in out Child) is > begin > Do_Something(Object); > Initialize(Parent(Object)); > end Initialize; Hmm. The understanding in C++ is that in a constructor, all of the base constructors have completed, so all facilities of the base classes are available to be used in the derived class constructors. I'm not saying that this first idiom you describe is wrong for Ada, but it does seem to force derived classes into having very intimate knowledge of the needs of their bases. What if initializing the child fields requires making calls to base methods? > procedure Initialize(Object: in out Child) is > begin > Object := (Parent_Type with ...); > Do_Something_Else(Object); > end Initialize; Nice. In C++ it is highly discouraged to implement constructors via assignment (because it is fragile and error-prone). If I'm not mistaken, this code will cause Finalize to be called on Object before the assignment takes place, which means that it's possible for Finalize to be called on an object before any Initialize for it has completed. I really have to stop thinking of Initialize/Adjust/Finalize as being equivalent to C++'s constructor/assignment/destructor. It may just be that I haven't gotten my mind around it properly, but it seems to me that Ada OO is significantly harder to understand and explain than Java's or C++'s, even (or especially) for simple cases. > So yes, there are areas where user written code can access an object > that has not yet been completely initialized. But in practice, as a > user you will find that once you get rid of any bugs (and exceptions) > inside Intialize, Adjust, and Finalize, that code written by others, > including the authors of types derived from your types, cannot mess up > the invariants of your type. I agree. But that's why I said that DK was wrong. Our discussion has been about code that runs during object construction and destruction. That is, the process of getting rid of the bugs and exceptions that you mention. > No, I did not say that. I said that attempts to down convert an object > to a child type will fail. That's not what I was talking about. I was saying that in a parent Initialize, the object could be view-converted to its classwide type, and then a dispatching call to could be made on the converted object which would wind up calling an overridden method of the child's type. Think of the template-method design pattern for example. (This would be in your idiom one code, but with the parent's Initialize called *before* the Do_Something(Object), because Do_Something requires that its base classes be completely set up.) So overridden methods could wind up being called on incompletely prepared objects. This can't happen in C++. There, the dispatching would only go to methods of the class whose constructor or destructor is running. If such a method is abstract, the implementation generally arranges for the program to abort.