From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (from weis@localhost) by pauillac.inria.fr (8.7.6/8.7.3) id KAA00266 for caml-redistribution; Tue, 12 Jan 1999 10:45:44 +0100 (MET) Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id TAA19623 for ; Mon, 11 Jan 1999 19:52:59 +0100 (MET) Received: from miss.wu-wien.ac.at (miss.wu-wien.ac.at [137.208.107.17]) by nez-perce.inria.fr (8.8.7/8.8.7) with ESMTP id TAA01732 for ; Mon, 11 Jan 1999 19:52:57 +0100 (MET) Received: (from mottl@localhost) by miss.wu-wien.ac.at (8.9.0/8.9.0) id TAA00822 for caml-list@inria.fr; Mon, 11 Jan 1999 19:52:57 +0100 (MET) From: Markus Mottl Message-Id: <199901111852.TAA00822@miss.wu-wien.ac.at> Subject: subtyping and inheritance To: caml-list@inria.fr (OCAML) Date: Mon, 11 Jan 1999 19:52:57 +0100 (MET) X-Mailer: ELM [version 2.4 PL21] MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Sender: weis Hello again, this time a question about inheritance and subtyping... Let's consider the following code snippet: --------------------------------------------------------------------------- class foo = object (self:'self) method x = "x" method eq (other:'self) = if self#x = other#x then true else false end class bar = object inherit foo method y = "y" end let f = new foo and b = new bar ;; print_string (string_of_bool (f #eq f)); print_newline (); print_string (string_of_bool (b #eq b)); print_newline (); --------------------------------------------------------------------------- So far no problem. Class "bar" inherits from "foo" and adds a method. The program will print out two times "true", because objects of type "foo" can be tested for equivalence within their class and objects of type "bar" as well. But now, I would really like to compare objects of type "foo" with objects of type "bar" as in: --------------------------------------------------------------------------- print_string (string_of_bool (f #eq (b :> foo))); print_newline (); --------------------------------------------------------------------------- This is, of course, not possible, because "bar" is not a subtype of "foo" and thus, cannot be coerced to "foo". But "bar" inherits everything from "foo" so I think it would be safe to call methods ** as they are defined in "foo" **. I think the problem occurs because of the following rule taken from the OCAML manual: Only the last definition of a method is kept: the redefinition in a subclass of a method that was visible in the parent class overrides the definition in the parent class. This rule prohibits that definitions as they appear in the parent class may be reused in case that an object of a subclass (in terms of inheritance, not subtyping!) shall be seen from the parent's "point of view". In the upper case, method "eq" is automatically redefined, because it has the type "'self" in its signature. Actually, *this* is the problem, not the additional method "y" as is stated at the end of the error message generated on the last "print_string...". My specific problem is: I have a program with classes for "terminal" and "nonterminal" symbols. Both inherit from a base class "symbol". The symbol class inherits from a class "ord", which defines a virtual method "compare". This allows me to compare terminals with terminals and nonterminals with nonterminals, but it also allows comparison between symbols (all three classes redefine "compare"). Look at this graph: ord -> defines virtual method "compare" | symbol -> redefines "compare" / \ terminal nonterminal -> both redefine "compare" But the problem is: I will never be able to compare terminals and nonterminals with each other, because the appropriate comparison method as defined in "symbol" has been "forgotten" - it is redefined in all child classes. Thus, I am not able to coerce them to "symbol". I have worked around this with the following inheritance scheme: ---- ord ----- -> defines virtual method "compare" | | | symbol | -> has a method "compare_symbol" | / \ | terminal nonterminal -> both redefine "compare" Although it is now possible to coerce terminals and nonterminals to symbols and have them thus compared via "compare_symbol", I am not content with this scheme: I would really like to have all methods from "ord" in "symbol", which all make use of the virtual "compare" method. I am neither sure whether I am overlooking some clever trick to get the result I want, nor whether a change in the handling of coercions ("memory" for methods of parent classes) is really safe. But at the moment I cannot think of any way to circumvent type safety. Comments on this welcome! Best regards, Markus -- Markus Mottl, mottl@miss.wu-wien.ac.at, http://miss.wu-wien.ac.at/~mottl