comp.lang.ada
 help / color / mirror / Atom feed
From: ncohen@watson.ibm.com (Norman H. Cohen)
Subject: Re: OO Idiom: Interfaces for derived classes
Date: 1996/03/21
Date: 1996-03-21T00:00:00+00:00	[thread overview]
Message-ID: <4is6mk$1dn6@watnews1.watson.ibm.com> (raw)
In-Reply-To: mmannohpq347p.fsf@ibm.net

In article <mmannohpq347p.fsf@ibm.net>, mmann@ibm.net (Gerd Moellmann) writes: 

|> After studying the ARM and "Ada as a second language" (Normal
                                                               ^
This is an abnorman way to spell my name, but that's okay.  I've been
called worse things than "normal". ;-)

|> H. Cohen, 1996), I came to the conclusion that Ada as a language does
|> not directly address/ has no apparently obvious approach wrt
|>
|>    whether it is desirable to separate interfaces for clients of
|>    classes vs. derived classes, and if so, how to implement the
|>    separation.
...
|> These were the reasons I got to the following coding idiom: 
|>
|>    o For every tagged type "base" in a package "base_package", the
|>    public interface of "base" is declared in "base_package" as
|>    normally for ADTs.
|>
|>    o Functions and procedures needed for derived class implementation
|>    are declared in the private section of "base_class" when they must
|>    be primitive.
|>
|>    o A child package "base_class.derived" contains, in its public
                         ^^^^^^^^^^ (Presumably you mean base_package.)
|>    interface, functions/procedures that together form the interface of
|>    "base" for derived classes.  These functions may access private
|>    functions/ data of "base" because "base_package.derived" is
|>    considered to be part of class "base".
|>
|>    o A derived class "derived" is implemented in a package
|>    "derived_package" that is not a child package of "base_package" to
|>    prevent "derived" from relying on the private implementation of
|>    "base".
|>
|>    o "derived" uses the public interface of "base" together with the
|>    services in "base_package.derived" for its implementation.
|>
|> What are your thoughts about it?  Do you think it is as important as I
|> do?  Are there perhaps other ways of doing it?

Note that your solution still requires voluntary compliance with a
convention--that only units implementing derived classes should contain
with clauses for base_package.derived.

Rather than trusting the whole rest of the program, I prefer the
"traditional" solution of declaring descendents of base_class in child
packages of base_package, which is more straightforward and only requires
trusting the writers of those child packages to use declarations in the
private part of base_package appropriately.

(If you are not the trusting sort, you can use an access-management
tool to ensure that no "unauthorized" children of base_package are
written.  After all, you must trust programmers not to make unauthorized
changes to the text of base_package itself, or else enforce this with an
access-management tool.  Page 471 of _Ada_as_a_Second_Language_ states,
"In a sense, since a child unit is logically nested inside its parent,
the author of a child package creates a modified version of the parent
package.  Only a programmer who would be trusted to modify the text of
the parent itself should be trusted to write a child unit of a package
with a private part.")

The situation gets more complicated when we turn our attention from a
snapshot, or release, of a program to a program as an living entity that
evolves over time, or to the distribution as a reusable component of a
package providing some OO class.  Then it becomes important for the
writer of the parent package to provide documentation distinguishing
those aspects of the parent package that represent supported parts of its
interface from those parts of the parent package that represent
implementation choices that may change in future releases of the parent
package.  At one extreme, the writer of the parent might guarantee the
proper functioning of the package only as long as no children are written
for it.  At the opposite extreme, the writer of the parent may commit to
preserving all the declarations in the private part of the package in all
future releases.  But the child should ask not (just) what the parent can
do for it; the child should ask too what it can do for (or to) its
parent:  If the writer of the parent does not rule out child packages
entirely, he must also document those invariants that all children of the
package must preserve if the package is to continue to function
correctly.

Back to the idiom you propose:  The usual reason for a derived class
referring directly to members of a base class is efficiency.  If you are
going to force all manipulations of the base-class implementation to be
through subprograms exported by Base_Package.Derived anyway, you lose the
motivation for giving implementations of derived classes special
privileges.  Why distinguish then between operations that are acceptable
only for derived classes to perform and those that are acceptable for all
clients to perform?  If you have truly hidden the implementation of the
base class from derived classes, then it would seem that any operation
deemed safe for the implementation of the derived class to perform will
also be safe enough for the world at large to perform.  If you have a
specific example that suggests otherwise, it would be interesting to see it.

Having said all that, if you really want to, there IS a way in Ada 95 to
mimic the C++ distinction between protected and private members, at the
cost of a level of indirection when accessing private members: 

   package P is
      type T is tagged private;
      ...
   private
      type Private_Components_Type;
      type Private_Components_Pointer_Type is access Private_Components_Type;
      type T is tagged
         record
            ...  -- "protected" components declared here
            Private_Components : Private_Components_Pointer_Type;
         end record;
   end P;

   package body P is
      type Private_Components_Type is
         record
            ... -- "private" components declared here
         end record;
      ...
   end P;

The "protected" components are visible in the private parts and bodies of
children of P, but the "private" components are not.

--
Norman H. Cohen    ncohen@watson.ibm.com




  reply	other threads:[~1996-03-21  0:00 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1996-03-21  0:00 OO Idiom: Interfaces for derived classes Gerd Moellmann
1996-03-21  0:00 ` Norman H. Cohen [this message]
1996-03-22  0:00   ` Gerd Moellmann
1996-03-22  0:00     ` Norman H. Cohen
  -- strict thread matches above, loose matches on Subject: below --
1996-03-22  0:00 Jean-Pierre Rosen
1996-03-22  0:00 ` Gerd Moellmann
1996-03-22  0:00 ` Norman H. Cohen
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox