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,4f071b0868ee342f X-Google-Attributes: gid103376,public From: Matthew Heaney Subject: Re: Design Question: How Best To Structure Cross-Referencing Types In Ada 95 Date: 1999/01/31 Message-ID: #1/1 X-Deja-AN: 438936462 Sender: matt@mheaney.ni.net References: <36A68FCA.E1EEAFFE@hiwaay.net> <78vonc$793$1@plug.news.pipex.net> NNTP-Posting-Date: Sat, 30 Jan 1999 22:17:28 PDT Newsgroups: comp.lang.ada Date: 1999-01-31T00:00:00+00:00 List-Id: "Nick Roberts" writes: > It might (but not necessarily) be appropriate to organise the packages a > little, e.g. by making Cars, Parts etc. children of Root_Cars. I don't agree, because the package Root_Cars is intended only as a work-around, not as a "real" package. If you pretend for the moment that Ada doesn't have this "problem," then you would structure the packages with package Cars as the root of the subsystem. The package Root_Cars isn't part of the package hierarchy. It exists only to serve as the home for the forward declaration of a type, a declaration unnecessary in a "better" version of the language. > As a tiny matter of style, you might want to choose names thusly: > "Cars" instead of "Root_Cars", and then "Ford_Cars", "GM_Cars", > "BMW_Cars", "Ford_Parts", "Lucas_Parts", etc. instead of "Cars", > "Parts", etc. (i.e. the children packages with derived types are > progressively _specialising_). [I've no doubt Matt chose the names he > did to simplify the example.] Just so there's no confusion about my solution: type Cars.Car is the ONLY type that derives from Root_Car. The type Car, NOT Root_Car, is the "real" root of the hierarchy. That Car derives from Root_Car is sort of an implementation detail that we had to show in the spec. This point is perhaps made more clear using a different name: package Forward_Declaration_Of_Type_Cars_Dot_Car is type Parent_Of_Type_Cars_Dot_Car_ONLY is abstract tagged null record; end; with Forward_Declaration_Of_Type_Cars_Dot_Car; use ... package Cars is type Car is new Parent_Of_Type_Cars_Dot_Car_ONLY with private; ... end Cars; Specialized cars would be declared in children of package Cars, which is the root of the package hierarchy. > This design (with tagged types) gives you the extensibility that OO people > are always banging on about: you can add a new type of car or part without > (in general) having to recompile any of the other packages. On larger > systems this can help prevent you wearing your teeth down on the edge of the > desk (waiting to recompile). But realize that we only made this type tagged because we needed to forward declare the Car type, because of a mutual dependency between specs. We used a tagged type because there is no other way to effect the work-around. In a slightly different language, type Car wouldn't have to be tagged. Not every abstraction has to be implemented as a tagged type. I avoid making a type tagged, unless I have a good reason to (because it's part of a type hierarchy). > In implementation terms, the tag check costs about 5-10 instructions, and > about 2-4 clock ticks for success (on a typical modern 32-bit processor, > with Optimise(Time) in force, excluding crap compilers). Unless you have a > really good reason not to, I would suggest you just live with this check: it > is likely to save you being skewered by a deep bug one day. But that would mean a developer was breaking a rule (that isn't enforceable by the language), by deriving from the abstract parent type of type Car. I wouldn't call this a "deep bug." Rather, it's a symptom of the programmer's unfamiliarity with the idiom of how to simulate mutual dependencies between package specs.