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.8 required=5.0 tests=BAYES_00,INVALID_DATE autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 109fba,66253344eaef63db X-Google-Attributes: gid109fba,public X-Google-Thread: 103376,66253344eaef63db X-Google-Attributes: gid103376,public X-Google-Thread: 1108a1,66253344eaef63db X-Google-Attributes: gid1108a1,public X-Google-ArrivalTime: 1994-09-28 20:10:05 PST Newsgroups: comp.lang.ada,comp.object,comp.lang.c++ Path: bga.com!news.sprintlink.net!howland.reston.ans.net!cs.utexas.edu!convex!news.duke.edu!news-feed-1.peachnet.edu!paperboy.wellfleet.com!noc.near.net!ray.com!news.ray.com!news.ed.ray.com!swlvx2!jgv From: jgv@swl.msd.ray.com (John Volan) Subject: Re: Mut. Recurs. in Ada9X w/o Breaking Encaps.? (LONG) Date: Thu, 29 Sep 1994 02:12:09 GMT Message-ID: <1994Sep29.021209.20769@swlvx2.msd.ray.com> References: <1994Sep27.165203.9192@swlvx2.msd.ray.com> <36bt0c$17oo@watnews1.watson.ibm.com> Sender: news@swlvx2.msd.ray.com (NEWS USER) Keywords: Ada 9X, C++, object-oriented Organization: Raytheon Company, Tewksbury, MA Xref: bga.com comp.lang.ada:6280 comp.object:6877 comp.lang.c++:30878 Date: 1994-09-29T02:12:09+00:00 List-Id: NHC = ncohen@watson.ibm.com (Norman H. Cohen) writes: NHC>One variation on this is to declare recursive types meant to serve as the NHC>parents of types Employee and Office, but to provide no operations for NHC>these recursive types. Then, in child packages, declare Employee and NHC>Office themselves as derived types and declare primitive operations in NHC>those child packages: NHC> NHC> with ... ; -- other stuff needed by Employee NHC> with ... ; -- other stuff needed by Office NHC> NHC> package Employees_And_Offices is NHC> NHC> type Employee_Parent is tagged limited private; NHC> type Employee_Pointer is access all Employee'Class; NHC> NHC> type Office_Parent is tagged limited private; NHC> type Office_Pointer is access all Office'Class; This solution suffers from the same problem as Mark Biggar's suggestion: These access types only give clients an "opaque" view of the designated objects. The useful primitive operations for these objects won't be declared until we get to the concrete *subclasses* declared later. So a client would have to resort to using a non-typesafe Unchecked_Conversion to "downcast" one of these pointers into designating the corresponding concrete subclass. Another issue is whether the concrete subclasses declared below are going to be the *only* subclasses of these abstract classes. Certainly that's the original intent -- but will a maintainer pay any attention? ;-) NHC> private NHC> NHC> type Employee_Parent is tagged NHC> record NHC> ... -- various components involving that "other stuff" NHC> Its_Occupied_Office : Office_Pointer; NHC> ... NHC> end record; NHC> NHC> type Office_Parent is tagged NHC> record NHC> ... -- various components involving that "other stuff" NHC> Its_Occupying_Employee : Employee_Pointer; NHC> ... NHC> end record; NHC> NHC> end Employees_And_Offices; Another problem here is that this doesn't really solve the original puzzle I posed: How do you avoid breaking encapsulation *between* these two classes? These type declarations are private, but since the packages below are all children of this parent package, they have complete visibility to the private part of the parent. So an Employee subprogram still has license to ignore the public primitives of the Office class and "diddle" with the Office's private components directly. (And vice versa.) NHC> package Employees_And_Offices.Employees is NHC> type Employee is tagged private; NHC> No_Employee : constant Employee_Pointer := null; NHC> ... -- Employee subprograms involving that "other stuff" NHC> private NHC> type Employee is new Employee_Parent with null record; NHC> end Employees_And_Offices.Employees; NHC> NHC> package Employees_And_Offices.Offices is NHC> type Office is tagged private; NHC> No_Office : constant Office_Pointer := null; NHC> ... -- Office subprograms involving that "other stuff" NHC> private NHC> type Office is new Office_Parent with null record; NHC> end Employees_And_Offices.Offices; NHC> NHC> NHC> with Employees_And_Offices.Employees, Employees_And_Offices.Offices; NHC> NHC> package Employees_And_Offices.Common is NHC> NHC> function Office_Occupied_By (The_Employee : in Employee) NHC> return Office_Pointer; NHC> NHC> function Employee_Occupying (The_Office : in Office) NHC> return Employee_Pointer; NHC> NHC> procedure Occupy (The_Office : in Office_Pointer; NHC> The_Employee : in Employee_Pointer); NHC> NHC> end Employees_And_Offices.Common; NHC> NHC>The operations in the Common child are not primitive operations of either NHC>type. (Two types cannot possibly both have primitive operations with NHC>parameters of the other type, because the declarations of the packages NHC>declaring those types would have to name each other in with clauses. If NHC>you don't mind breaking the symmetry, you can make the Offices child NHC>depend on the Employees child and put ALL the common operations in the NHC>Offices child as primitive operations of type Office, or vice versa.) NHC>The bodies of all three child packages have complete visibility into the NHC>mutually recursive data structure declared in Employees_And_Offices. Since NHC>Office_Pointer is declared to designate Office_Parent'Class rather than NHC>Office_Parent, there is no problem with Office_Pointer values designating NHC>Office objects, and similarly for the Employee-related types. Ah, but there *is* a problem: An Office_Pointer does't manifestly designate an *Office* object. Rather, it designates an *Office_Parent view* of what *might* be an Office object. This view, being "opaque", is not useful to a client. NHC> NHC>-- NHC>Norman H. Cohen ncohen@watson.ibm.com Well, this doesn't really work, but I think we're starting to get closer ... Thanks anyway! -- John Volan -------------------------------------------------------------------------------- -- Me : Person := (Name => "John Volan", -- Company => "Raytheon Missile Systems Division", -- E_Mail_Address => "jgv@swl.msd.ray.com", -- Affiliation => "Enthusiastic member of Team Ada!", -- Humorous_Disclaimer => "These opinions are undefined " & -- "by my employer and therefore " & -- "any use of them would be " & -- "totally erroneous."); --------------------------------------------------------------------------------