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.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,dad94612ff745427 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news4.google.com!news.glorb.com!news2.volia.net!newsfeed01.sul.t-online.de!t-online.de!news.belwue.de!newsfeed.arcor.de!news.arcor.de!not-for-mail From: "Dmitry A. Kazakov" Subject: Re: Instantiating private types with discriminants? Newsgroups: comp.lang.ada User-Agent: 40tude_Dialog/2.0.15.1 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Reply-To: mailbox@dmitry-kazakov.de Organization: cbb software GmbH References: <1147252198.138173.203910@j73g2000cwa.googlegroups.com> <44623869$0$4504$9b4e6d93@newsread2.arcor-online.net> <87d5elk8e9.fsf@ludovic-brenta.org> Date: Thu, 11 May 2006 12:28:20 +0200 Message-ID: <13byov3p0dqhk.yglz3nh5rpb8$.dlg@40tude.net> NNTP-Posting-Date: 11 May 2006 12:28:20 MEST NNTP-Posting-Host: 42f1bc12.newsread2.arcor-online.net X-Trace: DXC=JBMSj2S`8F2CDTkn::RD0?Q5U85hF6f;4jW\KbG]kaM8[NGU2GAcMG:95ImeW[h1P2WRXZ37ga[7:n919Q4_`Vj9NZZj5LgkU<7 X-Complaints-To: usenet-abuse@arcor.de Xref: g2news2.google.com comp.lang.ada:4196 Date: 2006-05-11T12:28:20+02:00 List-Id: On Thu, 11 May 2006 08:27:18 GMT, rick H wrote: > Dmitry A. Kazakov wrote: >> On Wed, 10 May 2006 16:52:32 -0500, Rick H wrote: >> >>> But all this has a side-effect that I haven't considered: the fact >>> that a variable declared as a class-wide type *requires* initialization >>> means that the compiler can determine the variable's type statically. >> >> No. It only means that the type should be determinable at run-time. There >> are may ways to do it. You can call a function with a class-wide result. >> >> It might be especially interesting to take a look at S'Class'Input >> attribute. It "dispatches" on a "bare" tag. [ Ada 2005 will offer a >> mechanism for fully user-defined things like this. See >> Generic_Dispatching_Constructor. ] >> >>> This means that the following will raise a constraint error: >>> declare >>> Var_A : General_T'Class := Get (10); -- Type_A >>> begin >>> Put (Var_A); >>> Ada.Text_IO.New_Line; >>> Var_A := Get (100.0); -- Type_B - constraint error! >>> Put (Var_A); >>> end; >> >> Yes, but this is a different thing. You cannot change tag, either >> dynamically or statically determined. Type mutators are no-no in Ada's type >> system. >> > Objects of class-wide types notwithstanding, I modified Ludovic's code > example to change Type_A and Type_B into linked-list elements. That > meant no more objects of class-wide type, You still have it the form of class-wide pointers (Linked_List_T). [ You can't get rid of class-wide types if you what to dispatch. ] > so I got rid of the Get > definitions. The following code does exactly what I wanted from this > cut-down example: a list of either-Integer-or-Floats. Next mystery: > what's the use of abstract subprograms? Put (X:in Type_A) and > Put (X:in Type_B) "feel" like just overloaded functions - why do they > "need" an abstract parent Put (X : in General_T)? Since General_T > is abstract, the latter Put will never be called. Or have I missed the > point again!? Puts might be overloaded in P, but it is rather a coincidence. More important is that they override Put of General_T. This is what allows you to dispatch to Put if you have some object of General_T'Class. Both overloading and overriding are forms of polymorphism, so yes, in that sense it is similar. The difference becomes obvious if you have moved declarations of Type_A and Type_B into separate packages. Or if you have defined a procedure to deeply put items: procedure Put_Them_All (Item : General_T'Class) is Iterator : Linked_List_T := My_List; begin Put (Item); -- Dispatches while Iterator /= null loop Put (Iterator.all); -- Dispatches Ada.Text_IO.New_Line; Iterator := Iterator.Next; end loop; end Put_Them_All; This procedure will work with any type derived from General_T without even knowing that any of them exist. This is so-called class-wide procedure - it works for the class rather than for individual types of. Note the a class-wide pointer like Linked_List_T dereferences to a class-wide object (General_T'Class). This is why Put (X.all) dispatches. To do this it does not need know anything else. [ Ada is a strongly typed language. ] A. Abstractness of a type statically ensures that no individual objects of this type will ever exist. B. Abstractness of a primitive subprogram statically ensures that it never be called. Any type with at least one abstract primitive subprogram has to be abstract. The reverse is wrong. You can consider declaration of: procedure Put (Item : in General_T) is abstract; as an abbreviation for: 1. there is no Put defined on General_T 2. there is Put defined on General_T'Class (it dispatches) If Put weren't abstract, then 1. would overload 2. That couldn't cause any conflict because the types are different: General_T /= General_T'Class. [...] > declare > Iterator : Linked_List_T := My_List; > begin > while Iterator /= null loop > Put (Iterator.all); > Ada.Text_IO.New_Line; > Iterator := Iterator.all.Next; You don't need "all" here: Iterator := Iterator.Next; Ada's pointers are transparent to record member/discriminant and array element (indexing) access. > end loop; > end; -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de