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,fa2cc518ef3b992c X-Google-Attributes: gid103376,public From: "Vladimir Olensky" Subject: Re: tagged types extensions - language design question Date: 2000/01/29 Message-ID: X-Deja-AN: 578932221 References: Organization: Posted via Supernews, http://www.supernews.com X-MimeOLE: Produced By Microsoft MimeOLE V4.72.3110.3 Newsgroups: comp.lang.ada X-Complaints-To: newsabuse@supernews.com Date: 2000-01-29T00:00:00+00:00 List-Id: Matthew Heaney wrote in message ... >In article , "Vladimir Olensky" > wrote: > >>>Why don't you just declare these types in separate packages? >> >> This is : >> 1. an additional step >> 2. an additional package >> 3. an additional level of inheritance. > >But you'd have the "additional package" in other OOP languages too. In >another language you'd have to declare two "classes," which means two >modules. Same as Ada. > (Although I think you can nest classes in C++, right?) Yes, I can nest classes in C++ and in Java. --- Two classes not always equal to two packages. Two classes could be in one file or in one enclosing class but two Ada packages are different files for which I should invent names. Also if I have an abstract root type with private and I extend it to another abstract tagged type with additional private fields and the last one is a parent to two concrete types both of them having the same public attributes then I should put that derived types in additional child package and duplicate that public attributes in each derived type instead of putting them (public attributes) in the abstract parent class. Also I should duplicate primitive operations on that attributes for each derived type instead of defining only one operation in the parent class or even at upper level root class. Or I should first create intermediate package in which public attributes are added to the abstract parent (name it as Root.Parent.PubAttr) and then in the final package to extend that abstract parent with private fields and then in the same package I can create non-abstract derived classes. I could not tell that it is very convenient. It would be better to have all this in one package. In C++ I can do that in just one step. Below is simple working C++ example (just created and tested): Type T is parent that has both public and protected part; Type T1 is a child that extends T with public and protected members in one step. No need in any additional intermediate class. -------------------------------------------------------- -- protected fields and members are the same as private -- but are visible in derived classes - the same as private -- components are visible in the child packages ------------------------- #include "stdafx.h"; class T { protected: // visible only in the derived classes int s ; public: int x,y; T() { s =2; x=3; y=4;}; // constructor }; class T1 : T { protected: int s1 ; public: int x1,y1; int Calculate () { return (s+s1)*(x+x1+y+y1); } T1() { s1 =3; x1=6; y1=7;}; }; int main(int argc, char* argv[]) { int result; T1 P; result = P.Calculate(); printf("result is %d \n", result); // result is 100 return 0; } ----------------------------------------------- >Because of the separation of module and type, it's possible to declare >intimately-relate types together in a single Ada package. In the normal >case --no public attributes-- this can be done quite easily: > >package P is > type T is tagged private; > type T1 is new T with private; ... >end P; This is exactly what I am doing for descendants that extend only private part of their parent and what I would like to have for derived types with both public and private attributes. >However, when you extend a type, the full view of the type has to be >known. That's why this: > >package P is > type T is tagged private; > type T1 is new T with record > I : Integer; > end record; >... >end P; > >is illegal. There's no way to know what components T1 has, >because the full view of T hasn't been seen yet. >From formal (LRM) point of view this is right. But from practical point of view this is right if we have only one pass compiler that does not know what it will have further in the compiled file. For two or more pass compiler this is not a problem. It gathers needed information during first pass and uses it at the next pass. (at least for Modula compilers that I know this is not a problem as well as for C++). >Normally there isn't a problem. But in your case, you want to have a >public component. If you're committed to declaring the types together >in one package, then you can declare the derived type without a public >component, and then: >1) declare a selector function if you want to let clients query the attribute >2a) declare a modifier procedure, to let clients set the attribute; or >2b) declare a modifier function, to let clients set the attribute >package P is > type T is tagged private; > type T1 is new T with private; > function Get_I (O : T1) return Integer; > procedure Set_I (O : in out T1; I : in Integer); > type IA is access all Integer; > for IA'Storage_Size use 0; > function Set_I (O : access T1) return IA; >end P; This is all good and well but all this is an additional work that could be avoided. >If you want to have some attributes public and some attributes private, >then you have to declare intermediate (abstract) types in which to do it. I had to do that and that's why I was asking my question. >It's hard to make hard and fast rules here, but in general, you should >use a package hierarchy to declare a type hierarchy. (This would be >required in other OOP languages as well.) This is what I am doing in reality but additional intermediate packages for derived types with public attributes break naming scheme in this chain. Regards, Vladimir Olensky