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 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,fba93c19bb4e7dbd X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-07-14 01:47:19 PST Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!newsfeed.icl.net!newsfeed.fjserv.net!newsfeed.freenet.de!fu-berlin.de!uni-berlin.de!tar-alcarin.cbb-automation.DE!not-for-mail From: Dmitry A. Kazakov Newsgroups: comp.lang.ada Subject: Re: Q: Endless loop by dispatching Date: Mon, 14 Jul 2003 10:48:26 +0200 Message-ID: References: <3F0ED2C8.6080409@snafu.de> NNTP-Posting-Host: tar-alcarin.cbb-automation.de (212.79.194.111) Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Trace: news.uni-berlin.de 1058172437 9366993 212.79.194.111 (16 [77047]) X-Newsreader: Forte Agent 1.8/32.548 Xref: archiver1.google.com comp.lang.ada:40255 Date: 2003-07-14T10:48:26+02:00 List-Id: On Fri, 11 Jul 2003 17:07:52 +0200, Michael Erdmann wrote: >Dmitry A. Kazakov wrote: > >>>Does any body know, what this loop causes?! I am not sure >>>if this is a bug or simply i missed the point. >> >> Serialize is class-wide and a view conversion does not change the >> tag..I.e. you have a re-dispatching case. Re-dispatching is a >> dangerous thing. [I would like it removed from Ada] >> >> So Serialize re-dispatches to B.Write which again calls Serialize. >> From design point of view, one should never call class-wide routines >> from specific ones, this warranties that dispatch happens only once. >> >> I suppose that you want sort of procedure expansion instead of >> complete overriding, if so, then you should explicitly call parent's >> Write, similarly as one does it for Initialize/Finalize: >> >Unfortuantly this was not the complete code. The Serialize was itended >to do a more complex job, which i have to replicate any where i want >to serialize an object. The original serialize code looks some what >like this: > >procedure Serialize( This : in Object'Class ) is > ........ > a := next(Attributes(This'Tag)) > while a /= null loop > Write( this.all, a.id ); > a := next(....); > end loop; > >end; > >The procedure write is a procedures which writes out a selected >attribute of an object. The procedure Serialize the complete >object. Thus from design point of view Write should never call Serialize. >I would have been great when i could write something >like this in ada: > >procedure Serialize( This : in Object'Class ) is > > Serialize( Super( This ) ); > > a := next(Attributes(This'Tag)) > while a /= null loop > Write( this.all, a.id ); > a := next(....); > end loop; > >end; It is a somewhat contradictory code. Serialize is either class-wide, or not. If it is then it should work for all Object'Class. Then it should not call itself. If it differs for different types then it has to be declared as a "normal" subroutine. I would split it in two: procedure Do_Serialize (This : Object'Class; As_If : Tag) is begin loop a := next (Attributes (As_If)); exit when a = null; Write (This, a.id); end loop; end Do_Serialize; procedure Serialize (This : in Some_Object) is begin Do_Serialize (This, Parent_Object'Tag); Do_Serialize (This, Some_Object'Tag); end Serialize; Though it is still a strange thing. Why parent's attributes cannot be extracted from an object using next? In other words, why do you want to extend Serialize? Why the following might be insufficient: procedure Serialize (This : Object'Class) is begin for Attribute in 1..Get_Number_Of_Attributes (This) loop Write (This, Attribute); end loop; end Serialize; >I think something like this does not exist in Ada!? Yes it does not. [Remote things] I wished Ada's OO be modified, 1. To have stricter contracts. Your case indicates an importance of contracts. When you write Object : constant Parent'Class := Create_Child; begin Foo (Parent (Object)); -- I am not what you think! you rightfully expect that the result be of Parent. But tagged types shamelessly break this. The result is not of Parent. It is still of Child because the conversion does not change the type tag. It is a clear contract violation, which leads to nasty surprises when later, in Foo, a re-dispatch happens. The source of the problem is that tag is a part of the object, so you cannot change it. OO-speaking the object has an identity which cannot be changed. It might be (and is) a great problem in other OOPL, but not in Ada which has T and T'Class different. So one might consistently state that T objects have no identity at all, while T'Class ones have it (through tag). And note, that nothing would be lost, because Rosen's trick would still allow you to add identity at your own risk. Alas, it wasn't made. If all types will become someday 'tagged', this should be changed. For present tagged types I would either forbid misleading view conversions to specific types or at least make them raising Constraint_Error if the source is not exactly of the target type: Parent (Object) -- Either illegal or Constraint_Error if not Parent Parent'Class (Object) -- Legal, and no surpises expected 2. To have an ability to refer the immediate parent [and visible ancestor] types. However, this feature should be carefully designed to keep a way free to multiple inheritance. Something like this: if X in S'Class then X'Super (S) is the most specific ancestor type in S'Class. For single inheritance case, it is abbreviated to S'Super. For tags 'Pred and 'Succ attributes should be defined to get tags along a derivation path: T'Pred (S) is the tag of a base type in S'Class, T'Succ (S) is the tag of a derived type in 'not S'Class or S' (all ancestors of S including S). Constraint_Error if the result does not exist or is ambiguous. --- Regards, Dmitry Kazakov www.dmitry-kazakov.de