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=-0.9 required=5.0 tests=BAYES_00,FORGED_GMAIL_RCVD, FREEMAIL_FROM autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,dbcfe2b0a74da57e X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!postnews.google.com!19g2000hsx.googlegroups.com!not-for-mail From: Maciej Sobczak Newsgroups: comp.lang.ada Subject: Re: Inherited Methods and such Date: Tue, 25 Sep 2007 13:53:51 -0700 Organization: http://groups.google.com Message-ID: <1190753631.240548.101820@19g2000hsx.googlegroups.com> References: <1190213376.707449.146640@g4g2000hsf.googlegroups.com> <1fl2wnziigxfd.1fjbag2hh8sbc$.dlg@40tude.net> <1190239986.762473.204290@k79g2000hse.googlegroups.com> <1rw45b3rmvmcr$.1df4wst5oknbl$.dlg@40tude.net> <1190296353.624737.150940@y42g2000hsy.googlegroups.com> <11m13st1f92kf$.m8s6y8mc8ebk.dlg@40tude.net> <1190321119.206313.65290@57g2000hsv.googlegroups.com> <1190408526.100291.265040@50g2000hsm.googlegroups.com> <9ukf2wtqjs0q$.iuijmal4x56b$.dlg@40tude.net> <1190497995.498679.119190@19g2000hsx.googlegroups.com> <1mw3qju08q8uj.sgzht7ld9ydc$.dlg@40tude.net> <1190579805.451187.71140@d55g2000hsg.googlegroups.com> <1i8ksr774bjbj.vpmnx3c0i9qz.dlg@40tude.net> <1190646125.024072.310020@19g2000hsx.googlegroups.com> <1r9s9v6pcjifl.vp4ktk0unpd1.dlg@40tude.net> NNTP-Posting-Host: 85.3.195.170 Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" X-Trace: posting.google.com 1190753631 7572 127.0.0.1 (25 Sep 2007 20:53:51 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Tue, 25 Sep 2007 20:53:51 +0000 (UTC) In-Reply-To: <1r9s9v6pcjifl.vp4ktk0unpd1.dlg@40tude.net> User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6,gzip(gfe),gzip(gfe) Complaints-To: groups-abuse@google.com Injection-Info: 19g2000hsx.googlegroups.com; posting-host=85.3.195.170; posting-account=ps2QrAMAAAA6_jCuRt2JEIpn5Otqf_w0 Xref: g2news2.google.com comp.lang.ada:2130 Date: 2007-09-25T13:53:51-07:00 List-Id: On 24 Wrz, 21:20, "Dmitry A. Kazakov" wrote: > > OK. Let's forbid to call virtual functions altogether until the full > > object is ready. I'm fine with such restriction. > > No, because: > > 1. It introduces another type T w/o primitive operations; Indeed. > 2. This degenerate is anyway inviable, as you can call primitive operations > from non-primitive ones. > > 3. There already exists a type that has the desired property of > non-dispatching, it is T (specific). 2. and 3. are inconsistent. > You are in an unresolvable contradiction by trying to mix class and its > truncations. It is untyped, just because mixing types in untyped. Ada 95 > solved that by naming the truncation as T and the class of as T'Class. The > rest was easy. Yes. Like here: -- p.ads: with Ada.Finalization; package P is type T is new Ada.Finalization.Controlled with null record; overriding procedure Initialize (X : in out T); procedure Some_Operation (X : in T); type R is range 10 .. 20; type S is new T with record I : R; end record; overriding procedure Initialize (X : in out S); overriding procedure Some_Operation (X : in S); end P; -- p.adb: with Ada.Text_IO; use Ada.Text_IO; package body P is procedure Dispatch (X : in T'Class) is begin Put ("Calling Some_Operation with T'Class"); New_Line (2); Some_Operation (X); end Dispatch; procedure Initialize (X : in out T) is begin Put ("P.Initialize for T"); New_Line; Put ("-> doing some operation with the object"); New_Line (2); Dispatch (X); end Initialize; procedure Some_Operation (X : in T) is begin Put ("P.Some_Operation for T"); New_Line (2); end Some_Operation; procedure Initialize (X : in out S) is begin Put ("P.Initialize for S, but first let's initialize T" & " and then we will take care of our (S) components"); New_Line (2); Initialize (T (X)); Put ("OK, finished with the supertype (T)"); New_Line; Put ("-> let's initialize our own (S) components..."); New_Line; X.I := 15; Put ("-> components initialized and now I =" & R'Image (X.I)); New_Line (2); end Initialize; procedure Some_Operation (X : in S) is begin Put ("P.Some_Operation for S"); New_Line; Put ("-> here we are SURE that all components are correct"); New_Line; Put ("-> for example I =" & R'Image (X.I)); Put (" which is SURELY in the range " & R'Image (R'First) & " .." & R'Image (R'Last)); New_Line; Put ("-> otherwise it would be UNTYPED MESS"); New_Line (2); end Some_Operation; end P; -- a.adb: with P; procedure A is X : P.S; begin null; end; $ gnatmake a gcc -c a.adb gcc -c p.adb gnatbind -x a.ali gnatlink a.ali $ ./a P.Initialize for S, but first let's initialize T and then we will take care of our (S) components P.Initialize for T -> doing some operation with the object Calling Some_Operation with T'Class P.Some_Operation for S -> here we are SURE that all components are correct -> for example I = 0 which is SURELY in the range 10 .. 20 -> otherwise it would be UNTYPED MESS OK, finished with the supertype (T) -> let's initialize our own (S) components... -> components initialized and now I = 15 $ The above program prints 0 as the value of an object which type is range 10 .. 20. What's even more funny, I can add the following inside Some_Operation for S: declare J : R := X.I; -- at this point X.I = 0 begin Put (R'Image (J)); end; Guess what will happen. No constraint_error and 0 is assigned to J. Why? Because the poor compiler assumed that if X.I is of type R, then no checks are necessary. Wow. > > Let's say I want to register my new object from T's constructor in > > some map or somewhere. I don't want to hook to complete T'Class, > > because I cannot force users deriving from my T to call be back so > > that I can register. I want the registration process to be > > encapsulated and invisible and I want to do it from T's constructor. > > If you restrict the possibility to use T'Class inside the constructor, > > you have to way to register T'Class reference/pointer from T's > > constructor. Too bad. > > I don't understand your example - if you don't derive from T, its > constructor will not be called. What do you want, to register objects of > the type T or objects of the type T'Class? Answer this and you will know > from where to do the registration of what. I want to register T'Class, but I don't want to involve those who derive from T. > > Another part is dispatch into > > vacuum. > > Not in Ada. You cannot dispatch in Initialize because its argument is > specific. See above example. > >>> What about growing up? > > >> The attributes do. > > > No. Children and Adults have different interfaces. It's not even the > > case-block-pretending-dispatch. There are different primitive > > operations, some of them not even rooted in Human. > > You could say it simpler: Children and Adult are different types. Period. They are both in Human'Class. You try to escape the problem instead of solving it. > >> My point is, a view is just a new object of a *new* type. > > > It does not have to be, but I find it acceptable except that I don't > > think you need a *new* type for them. > > We need it to prevent infinite recursion. More generally, here the > behavioral principle applies: if there is a difference between object and a > reference to => that should be observable through the behaviors of => they > have different behaviors => they have different types. What if they don't have different behaviors? There are two ways to achieve it: 1. Prevent anybody from interacting with the object directly, so there is nothing to compare (Java). 2. Make references just names, which are syntax entities (C++, in some contexts). > > Control question: what is the identity of the view? :-) > > There is nothing special in identity. A view can have many identities: > > 1. The name of the view > 2. The type of the view > 3. The target if the type of is comparable > 4. The tag of the view if it is polymorphic > 5. The tag of the target if that is polymorphic > ... 6. The identity of the target. > >> Ada is consistent because Initialize is not a constructor. It washes its > >> hands: if we don't know how to do it properly, we better don't. > > > Leaving the problem open? I don't call it consistent. > > Incomplete, but consistent. Absence of solution is better than a wrong one. A wrong solution is exploited in the example above. This is *really* *untyped* *mess* (tm). Let's also not forget that Initialize is useless as a constructor (and thus incomparable to C++) anyway due to the lack of parameters. But so- called "constructor functions" will not solve this problem. -- Maciej Sobczak http://www.msobczak.com/