comp.lang.ada
 help / color / mirror / Atom feed
From: ncohen@watson.ibm.com (Norman H. Cohen)
Subject: Re: Ada 90 inheritance request?
Date: 21 Dec 1994 16:02:11 GMT
Date: 1994-12-21T16:02:11+00:00	[thread overview]
Message-ID: <3d9ji3$kpa@watnews1.watson.ibm.com> (raw)
In-Reply-To: JGOODSEN.94Dec19135859@treasure.radsoft.com

In article <JGOODSEN.94Dec19135859@treasure.radsoft.com>,
jgoodsen@treasure.radsoft.com (John Goodsen) writes: 

|> In article <EACHUS.94Dec15184124@spectre.mitre.org> eachus@spectre.mitre.org (Robert I. Eachus) writes: 
|>
|>       Never being afraid to jump into the fray, I'll respond to John by
|>    taking his MI example and asking why the obvious Ada 95 version is not
|>    acceptable: 
|>
|>        type Needs_Finalization is new Controlled with...;
|>        -- overriding of Initialize/Adjust/Finalize
|>        procedure Initialize (Obj : in out Needs_Finalization);
|>        procedure Adjust     (Obj : in out Needs_Finalization);
|>        procedure Finalize   (Obj : in out Needs_Finalization);
|>
|>        type Ctrl_T is new T with record
|>       NF:  Needs_Finalization;
|>        end record;
|>
|>
|> Maybe it's just me not seeing something here (which could be an indicator
|> of the usability issues involved with addressing MI in Ada95), but where
|> is the polymorphic behavior in the MI lattice?  Wouldn't the above solution
|> require me to delegate methods to the NF member of Ctrl_T (by hand)?

Here's what I think you're not seeing:  EVERY Ada object, whether or not
it is a controlled type, gets "finalized" when it is about to cease to
exist.  Finalization consists of calling that object's Finalize procedure
if the type is controlled, and then finalizing each of the object's
components, whether or not the type is controlled.  (See RM95 section
7.6.1, paragraphs 6 through 9.)  Thus when a Ctrl_T object is about to
cease to exist, the Finalize procedure for type Needs_Finalization is
called for the NF component of that object.

(C++ works the same way.  The difference comes in the treatment of any
finalization code for ancestors.  In C++, the base class destructor is
unavoidably invoked after the destructor for the derived class; in Ada,
it is up to the programmer whether a Finalize procedure for a derived
controlled type should invoke its parent's Finalize procedure.)

Perhaps you forgot the context of the question that was posed.  No
requirement was stated for Ctrl_T to publicly inherit any "normal"
operations of Needs_Finalization.  Rather, Needs_Finalization was
presumed to be part of the IMPLEMENTATION of the extension.  There was a
misconceived requirement for Ctrl_T to inherit the Finalization operation
of Needs_Finalization, but Robert Eachus's construction shows that this
is unnecessary.

|>                          Can you give an example (besides the overused
|> diamond inheritance pattern) ?  What do you mean by "unsafe MI" ?

If the diamond inheritance pattern is "overused", that's because the
problems it presents are compelling, all by themselves.

But there is a more general safety issue.  In a language with MI, given
two arbitrary classes A and B, it is always possible to construct an
object that can be used as both an A and a B, so one cannot recognize
uses of an A as a B as illegitimate at compile time.  (The legitimate
uses, but they are so few and far between that it is not worth opening
gaping holes in the type system.)

This issue shows up in the new C++ dynamic_cast feature.  In Ada,
conversion from access-to-S'Class to access-to-T'Class is not allowed
unless S is derived from T or T is derived from S.  (If T is derived from
S, a run-time check is performed to ensure that the access-to-S'Class
value actually points to an object whose type is derived from T; if S is
derived from T, no run-time check is necessary.) In any other case, the
conversion is rejected as illegal at compile time.  In C++, a dynamic
cast from S* to T* is always legal at compile time.  It cannot be
rejected, because someone may later derive a class D from BOTH S and T,
in which case an S* pointing to a D can be safely converted to a T*.  (At
run time, the dynamic cast returns a null pointer if the S* value does
not point to an object of a class derived from T. :-( )

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



  parent reply	other threads:[~1994-12-21 16:02 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1994-11-23 21:33 Ada 90 inheritance request? S M Ryan
1994-12-02 16:46 ` Tucker Taft
1994-12-09 17:26   ` Cyrille Comar
1994-12-11 18:47     ` Bob Duff
1994-12-12  3:15     ` Tucker Taft
1994-12-13 19:02     ` John Goodsen
1994-12-14 19:49       ` John Goodsen
1994-12-15 18:41         ` Robert I. Eachus
1994-12-19 18:58           ` John Goodsen
1994-12-20 10:40             ` Robert I. Eachus
1994-12-21 16:02             ` Norman H. Cohen [this message]
1994-12-22  1:21             ` Bob Duff
1994-12-17 13:55       ` Tucker Taft
replies disabled

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