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: 103376,93fa00d728cc528e X-Google-Attributes: gid103376,public X-Google-Thread: 1108a1,93fa00d728cc528e X-Google-Attributes: gid1108a1,public X-Google-ArrivalTime: 1994-10-25 19:13:52 PST Newsgroups: comp.lang.ada,comp.object Path: nntp.gmd.de!xlink.net!fauern!news.th-darmstadt.de!terra.wiwi.uni-frankfurt.de!zeus.rbi.informatik.uni-frankfurt.de!news.dfn.de!Germany.EU.net!wizard.pn.com!satisfied.elf.com!news.mathworks.com!solaris.cc.vt.edu!tml.com!uunet!noc.near.net!ray.com!news.ray.com!news.ed.ray.com!swlvx2!jgv From: jgv@swl.msd.ray.com (John Volan) Subject: Re: Mutual Recursion Challenge Date: Mon, 24 Oct 1994 20:32:14 GMT Message-ID: <1994Oct24.203214.4967@swlvx2.msd.ray.com> References: <1994Oct18.221751.15457@swlvx2.msd.ray.com> <38289r$79m@oahu.cs.ucla.edu> <1994Oct19.143843.372@wdl.loral.com> <38fi4r$l81@oahu.cs.ucla.edu> Sender: news@swlvx2.msd.ray.com (NEWS USER) Organization: Raytheon Company, Tewksbury, MA Xref: nntp.gmd.de comp.lang.ada:16169 comp.object:16592 Date: 1994-10-24T20:32:14+00:00 List-Id: eachus@spectre.mitre.org (Robert I. Eachus) writes: > There are many features in Ada 9X which lead to a better approach >to OOP. In particular, the mindset problem here is that the mutual >recursion must be between peers. Ada 9X does a nice job on recursion >between objects at different levels of abstraction, and most of >difficulty in the examples comes from constructing two types at the >same level of abstraction and in different packages. > In my (so far limited, as is everyone's) experience in Ada 9X, you >are much more likely to be adding an abstraction, using a generic >mixins, when the need for recursion occurs. In those cases, all the >baggage discussed is either there for other reasons or not necessary. Could you clarify this a bit, and elaborate on how using mixins would work here? I think I understand what you're driving at, but perhaps other folks won't. What, precisely, do you mean by the "baggage" that would be there anyway? Also, how well does the mixin technique really scale up, when you imagine many classes, many associations, and each class participating in many associations? >It may seem that creating a dozen abstract types which are only there >as placeholders is a problem, but in fact the only problem I have >found with it is coming up with names. (The best strategy I have >found is to use the base class name joined with the generic package >name as the name of the package instance: > package Persons_Office_Assignment is new Office_Assignment(Person); > and elsewhere: > package Office_Staff_Assignment is new Staff_Assignment(Office); > As this particular instantiation should make clear, package >Staff_Assignment may also be used to add staff to projects, to >departments, etc. I take it that Persons_Office_Assignment would declare a derived type inheriting from Person, with an extension supporting the association with Office. Likewise, Office_Staff_Assignment would declare a derived type inheriting from Office, with an extension supporting the association with Person. One problem I see with this particular formulation is that a Person-who-can-occupy-an-Office can point to any Office, not necessarily only an Office-that-can-be-occupied; likewise, an Office-that-can-be-occupied can point to any Person, not necessarily only a Person-who-can-occupy-an-Office. Is there a way of putting this together that guarantees the invariant that if a Person occupies an Office, then that Office is occupied by that Person? >And in fact it might be better to have the >assignment package defined as a double generic as a much higher level >and instanced down, or just as a generic with two type parameters as >suggested earlier in this discussion. (In such a model, Person and >Office would be instances of Objects, and Assignment would create a >relationship.) Do you mean something like this? generic type Former_Base is tagged limited private; type Latter_Base is tagged limited private; package One_To_One_Association is type Former is new Former_Base with private; type Former_Pointer is access all Former'Class; type Latter is new Latter_Base with private; type Latter_Pointer is access all Latter'Class; ... -- Subprograms supporting association. Some may be primitives for -- either Latter or Former type, but none may be primitive for both. private type Former is new Former_Base with record Its_Latter : Latter_Pointer; end record; type Latter is new Latter_Base with record Its_Former : Former_Pointer; end record; end One_To_One_Association; There would be something similar for One_To_Many_Association and Many_To_Many_Association. Then we could instantiate it something like this: package Person is type Object is tagged limited private; ... -- primitives for ordinary attributes not involving associations end Person; package Office is type Object is tagged limited private; ... -- primitives for ordinary attributes not involving associations end Office; package Building is type Object is tagged limited private; ... -- primitives for ordinary attributes not involving associations end Building; ... etc. with Person; with Office; with One_To_One_Association; package Person_Occupies_Office is new One_To_One_Association (Person.Object, Office.Object); with Person_Occupies_Office; with Building; package Building_Contains_Office is new One_To_Many_Association (Building.Object, Person_Occupies_Office.Latter); ... etc. with Building_Contains_Office; package Total_Office is type Object is new Building_Contains_Office.Latter with null record; end Total_Office; with Building_Contains_Office; package Total_Building is type Object is new Building_Contains_Office.Former with null record; end Total_Buidling; with Person_Occupies_Office; package Total_Person is type Object is new Person_Occupies_Office.Former; end Total_Person; ... etc. Of course, the actual immediate parent type for each "Total" object type would depend on the particular mix of classes and associations in the specific application. If the requirements of the problem changed to add a new association to a class, we'd have to change where the given "Total" type derived from. And now for the "acid test": Can this technique meet the "Challenge" of getting a class into a mutually-recursive association with one of its own subclasses? with Person_Occupies_Office; package Manager is type Object is new Person_Occupies_Office.Former with private; ... -- primitives for ordinary attributes not involving associations end Manager; with Person_Occupies_Office; with Manager; with One_To_Many_Association; package Manager_Supervises_Person is new One_To_Many_Association (Manager.Object, Person_Occupies_Office.Former); with Manager_Supervises_Person; package Total_Manager is type Object is new Manager_Supervises_Person.Former with null record; end Total_Manager; -- Oh, and now we have to change how we define Total_Person: with Manager_Supervises_Person; package Total_Person is type Object is new Manager_Supervises_Person.Latter with null record; end Total_Person; But there's a problem here: Total_Manager.Object inherits from Manager_Supervises_Person.Former, which inherits from Manager.Object, which inherits from Person_Occupies_Office.Former. But Total_Manager.Object does not inherit from Manager_Supervises_Person.Latter. So a Total_Person can have a supervising Manager, but a Total_Manager is not a Total_Person, so it cannot have a supervising Manager of its own. It looks like this mixin technique results in "inheritance collision". Is there a way around this? At the very least, this mixin technique seems a very confusing way to build up classes. Even barring any "Challenging" situation, my gut feeling is that this technique sooner or later will collapse under its own weight. But at this point, I can't prove this rigorously. One thing that bothers me is that you have to pick some arbitrary order to build up all the associations, so that in the end the total view of each class includes all the associations it will participate in. This introduces arbitrary dependencies among the association instantiations that don't seem to mean anything within the problem domain, but which might have a detrimental impact on the software's resilience in the face of requirements change. If I'm totally mixed-up about mixins :-), please help me out. Thanks. -- 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."); --------------------------------------------------------------------------------