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.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no 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: "Matthew Heaney" Subject: Re: tagged types extensions - language design question Date: 2000/01/28 Message-ID: #1/1 X-Deja-AN: 578618900 Content-transfer-encoding: 7bit References: Content-Type: text/plain; charset="US-ASCII" X-ELN-Date: Thu Jan 27 20:49:22 2000 X-Complaints-To: abuse@earthlink.net X-Trace: newsread1.prod.itd.earthlink.net 949034962 38.26.88.151 (Thu, 27 Jan 2000 20:49:22 PST) Organization: EarthLink Network, Inc. Mime-version: 1.0 NNTP-Posting-Date: Thu, 27 Jan 2000 20:49:22 PST Newsgroups: comp.lang.ada Date: 2000-01-28T00:00:00+00:00 List-Id: 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?) 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; 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. 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; > That's why I was asking why it is not allowed to do this in one step as in > other OOP languages. Probably there exist some reasons for that. Mainly historical. Tucker can speak for himself, but his philosophy was to use existing syntax as much as possible. So instead of bolting a new "object-oriented corner" onto the language, he just took the existing syntax for inheritance: type NT is new T; and slightly modified it to add type extension: type NT is new T with private; > Though GNAT provides efficient dispatching mechanism it is better to > minimize inheritance depth for derived types when possible. 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. That's just happens to be the syntax. Forget about that fact that it increases the inheritance depth; that is irrelevant here. > Also creating additional packages just to provide visible fields for > private tagged type is not handy. That's not the reason for needing an additional package. Normally you wouldn't need the other package. Your problem is that you're trying to derive a type from a parent whose full view hasn't been declared yet. > Actually I was using additional packages but to my point of view this is not > very convenient. 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.) The exception is when you have a single abstraction that comprises more than one type: package Subjects_And_Observers is type Subject is tagged limited private; type Observer is tagged limited private; procedure Attach (Obs : access Observer; Sub : access Subject); ... end Subjects_And_Observers; Here co-location of the two types makes sense, because each type depends on the other's representation. It's one abstraction (the "observer" pattern, sometimes called "publish/subscribe") that is implemented as a pair of types. However, this is less common than the situation where the dependency is in one direction only. For a typical class (maybe broad, and hopefully shallow), it makes sense to declare the root type in a package, and each derived type in its own child package.