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.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,2ea02452876a15e1 X-Google-Attributes: gid103376,public From: donh@syd.csa.com.au (Don Harrison) Subject: Re: Choice of OO primitives in Ada95 Date: 1996/02/19 Message-ID: X-Deja-AN: 140048501 sender: news@assip.csasyd.oz references: <4g2f8v$15lc@watnews1.watson.ibm.com> organization: CSC Australia reply-to: donh@syd.csa.com.au newsgroups: comp.lang.ada Date: 1996-02-19T00:00:00+00:00 List-Id: Norman H. Cohen) wrote: :|In article , donh@syd.csa.com.au (Don Harrison) :|writes: : :|> Tucker Taft wrote: :|> :|> [...] :|> :|> : ... The orthogonality of :|> : types and modules in Ada 95 can be a major advantage, :|> : gives the programmer more flexibility in structuring their system :|> :|> What flexibility does this approach offer over conventionally encapsulated classes? : :1. It allows other forms of encapsulation and packaging, not involving : classes. We could have a package providing a nonextendible private : type for complex numbers, deferred constants zero, one, and i, and a : set of arithmetic operations. We could have a package providing a set : of constants. We could have a package providing a set of : higher-level auxiliary routines operating on a type provided by : another package, building on the primitive operations provided by that : package. I've seen people try to use C++ classes with no nonstatic : members for these other forms of encapsulation and packaging, and the : result is strained. That's one reason C++ has added namespaces, which : are like Ada packages. But once the full generality of Ada-like : packages is available, the class program unit as an encapsulation : mechanism is redundant. I don't question the value of packages for non-OO encapsulation. I am interested to know what is the perceived flexibility wrt OO. Did Tucker meant flexibility wrt non-OO encapsulation? :2. It allows data abstractions involving two or more intimately linked : types to be encapsulated together. For example: : : with Dates; use Dates; : package Family_Trees is : : type Marriage_Type is private; : type Person_Type is private; : : function New_Person : (Name : String; : Birth_Date : Date_Type; : Death_Date : Date_Type := No_Date); : : procedure Wed : (Husband : in out Person_Type; : Wife : in out Person_Type; : Marriage_Date : in Date_Type; : Divorce_Date : in Date_Type := No_Date; : Marriage : out Marriage_Type); : : procedure Add_Offspring : (Marriage: in out Marriage_Type; Child: in out Person_Type); : : function Husband (Marriage: in Marriage_Type) return Person_Type; : function Wife (Marriage: in Marriage_Type) return Person_Type; : function Marriage_Of (Spouse: in Person_Type) return Marriage_Type; : function Parents (Child: in Person_Type) return Marriage_Type; : : generic : with procedure Process_One_Child (Child: in Person_Type); : procedure Process_All_Children (Marriage: in Marriage_Type); : : generic : with procedure Process_One_Marriage (Marriage: in Marriage_Type); : procedure Process_All_Marriages (Spouse: in Person_Type); : : private : : ... : : end Family_Trees; This is an example of what I mean by tight-coupling of abstractions - you are forced to encapsulate both abstractions into a single module. :|> As far as symmetry between operands is concerned, the benefits seem to be more :|> theoretical than practical. : :The ability to use natural notation has the very practical advantage of :making programs easier to read and understand. I would say the opposite is true - forcing a whole bunch of different abstractions into the one module creates an amorphous mess that the developer has to sift through to see which operations relate to which abstractions. :|> Indeed, encapsulating classes has the practical :|> advantage of cleaner interfaces to classes. Cleaner interfaces facilitate easier :|> debugging, maintenance, reuse etc. The Ada 95 model works against this principle :|> by forcing designers to create tightly-coupled classes because parts of their :|> interfaces are shared. : :Ada does not "force" designers to do any such thing. Indeed, the :language encourages the use of encapsulated, loosely coupled data :abstractions. An example might best illustrate what I mean. Extending your example and assuming each type is tagged, we might have: package X is type MARRIAGE is tagged ... type PERSON is tagged ... type UNIVERSITY is tagged ... type GOVERNMENT is tagged ... type ELECTORATE is tagged ... type ADDRESS is tagged ... procedure Enrol (Student : in out PERSON; Uni : in out UNIVERSITY); procedure Award_Grant (Polies : in out GOVERNMENT; Uni : in out UNIVERSITY); procedure Make_Gerrymander (Polies : in out GOVERNMENT; Elect : in out ELECTORATE); function Office_Address (Elect : in ELECTORATE) return ADDRESS; end X; Each abstraction is related to the previous one but isn't necessarily related to any other. As I understand it, the language rules dictate that each of these abstractions must be in the same package. But many of them have nothing to do with each other. They are tightly-coupled even though they should be distinct and this has been forced by the language rules. :|> Forcing ownership of operations by particular classes is entirely consistent with :|> the pattern established in Ada 83 for packages: the components of a package OWN :|> their components (attributes, operations, etc.). Therfore, mapping classes onto :|> packages giving package classes follows quite naturally as shown by my model. : :Ada certainly recognizes a close relationship among packages, types, and :operations: If a package provides both a type and subprograms with :parameters or results of that type, those subprograms "belong" to the :type. (In the technical jargon, they are "primitive operations" of the :type.) : :But a package is a module, not a type. The unnatural modeling of :one-per-class data items as static "members" in C++ comes from an attempt :to force-fit the two concepts into a single construct. In Ada, a :singleton data item is simply a variable declared inside a :package--encapsulated in the package body if it is to be hidden (like a :C++ private static data member). There is no pretense that the variable :is in any way a COMPONENT of any type that happens to be encapsulated in :the same package as the variable. I can't make any comment on C++ as I'm unfamiliar with it (must be the only one in the world). The Eiffel equivalent of static members are probably 'once' attributes which may optionally be exported (visible or private). This issue is language war flame bait and I don't intend to defend the pure OO position here :-) : :-- :Norman H. Cohen ncohen@watson.ibm.com Don.