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.7 required=5.0 tests=BAYES_00,INVALID_DATE, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!apple!oliveb!orc!Ozona!chase From: chase@Ozona.orc.olivetti.com (David Chase) Newsgroups: comp.lang.ada Subject: Re: Does Ada really need MULTIPLE inheritance? Message-ID: <48695@ricerca.UUCP> Date: 17 Oct 89 20:49:41 GMT References: <8910161521.AA27039@ajpo.sei.cmu.edu> <503@h.cs.wvu.wvnet.edu> Sender: news@orc.Olivetti.Com Reply-To: chase@orc.olivetti.com (David Chase) Organization: Olivetti Research California, Menlo Park, CA List-Id: I'm not well-versed in Ada, but people I've talked to ensure me that Ada has something similar to the "opaque types" of Modula-2 and Modula-3. Combining opaque types and multiple inheritance can lead to some nasty problems. I don't have a solution; just a problem. I'm assuming that by "multiple inheritance", the people discussing it means the ability to (1) extend an existing type or (2) refine an abstract (virtual, in the C++ lingo) type. In the first case one might specialize "vehicle" into "car" and "truck"; in the second case, one might provide a method for "compare" for an abstract "Comparable", and take advantage of all the code already written to deal with Comparable objects. It's the second case, and overriding of existing message-method bindings in general, that causes the problem. Suppose I have a type T1, and it has a binding message-method binding M1-m1a (M1 is the message, m1a is the method for it). Supposing I have a type T2 which inherits from T1, and uses the M1-m1a binding. T1 = OBJECT METHODS M1() := m1a END; T2 = T1 OBJECT METHODS ... END; Now suppose I export T2 opaquely, along with a procedure P2 which does something useful with a T2. OPAQUE OBJECT T2; (* I'm making up syntax as I go along *) PROCEDURE P2(x:T2) ...; Now suppose I have a type T3 which inherits from T2, and also inherits from T1, but uses the message-method binding M1-m1b. I claim that (1) this should be legal, because the programmer has no way of knowing that it should be illegal (information hiding, right?) (2) An object O of type T3 should have the binding M1-m1b where it is visible that O is a T3 (because that's what the programmer said) (3) An object O of type T3 should have the binding M1-m1a whenever it is in a context where it is known to be a T2, but not known to be a T3 (because the programmer should not be able to invalidate the correctness of a module if the internals of the module are hidden). That is (elaborating (3)) if P2 is called, then within P2 the binding should be M1-m1a, and if O.M1 is sent in that context, then within the code for m1a the binding should still be M1-m1a. That is, a second time, changes to the method bindings for T1 by a subtype T3 *must not* change the behavior of T3 when considered as a T2; any proofs about the behavior of a T2 would thus go out the window (and the programmer would be clueless, because the dependence of T2 on T1's message-method bindings is hidden). T3 = T1, T2 OBJECT METHODS M1 := m2b END; at some point in the program, VAR x : T3; ... P2(x); (* x MUST act as a T2 in P2, including the binding of M1 to m1a. *) ... x.M1() (* This MUST call method m1b, not m1a. *) I am *not* arguing that this should be the case if T2 is not opaque; in that case everything is in the clear, and either an error message or a change in T2's behavior is allowed. This nasty situation could be avoided by creative prohibition (objects cannot be opaquely exported -- yuck; opaque types cannot be inherited -- yuck; no multiple inheritance -- many people say yuck, but that's what we live with in Modula-3), but I'd be even happier if I could figure it out. David