Path: utzoo!attcan!uunet!decwrl!sdd.hp.com!samsung!cs.utexas.edu!rice!uupsi!sunic!tut!tukki.jyu.fi!sakkinen From: sakkinen@tukki.jyu.fi (Markku Sakkinen) Newsgroups: comp.object Subject: Re: inheritance and `type loss' Message-ID: <1990Jul26.120125.7955@tukki.jyu.fi> Date: 26 Jul 90 12:01:25 GMT References: Reply-To: sakkinen@jytko.jyu.fi (Markku Sakkinen) Distribution: comp Organization: University of Jyvaskyla, Finland Lines: 109 In article sra@ecs.soton.ac.uk (Stephen Adams) writes: >This might be a naive question, but it has been puzzling me >for a while. Consider the class integer. This class >supports two methods: > > + which takes another integer and returns the sum > image which returns a string denoting the integer > as a decimal number > >so 2+4 -> 6 and (6).image -> "6" > >Suppose I create a subclass called roman. I provide a new >method called image which returns roman numerals e.g. >roman_6.image -> "VI". The + operation is inherited from >integers. This is a very good question, in fact. The great majority of OO languages treats basic types such as integer differently from ordinary classes. There are two main approaches: 1. Simula and many others (including C++ and Eiffel) don't even pretend that 'integer' is a class; thus you cannot create any subclasses from it. 2. Smalltalk and some other languages pretend that 'integer' is a class just like any other. However, it is almost impossible to define subclasses that make any sense (I'll qualify this below). The problem at hand means that it is only desired to override one superclass method in the subclass, thus instances of the subclass should be completely similar to instances of the superclass. If OOP is as great for code reuse as advertised, then clearly one should not be required to write anything but the overriding method in the subclass definition. In Smalltalk-80, Integer happens to be an abstract class, so in Smalltalk we must take some concrete subclass (e.g. SmallInteger) to stand for 'integer' above. (The problem is different for an abstract superclass: '+' may not be implemented there at all, and indeed it isn't in Smalltalk's Integer class.) The instances of such Smalltalk classes as SmallInteger are immutable, and they are conceptually never created; all occurences of e.g. '5' can be regarded to refer to the same immutable object. It would seem to me that if one defines Roman as a subclass of SmallInteger, there is no way to create an instance of Roman with a given value. It appears that for the problem to be solvable, 'integer' must be a user-defined class both in Simula-like and Smalltalk-like languages. Let's call it 'MyInteger' to make this clear. It will obviously need exactly one instance variable, which is an ordinary integer. It will also need an initialisation method (constructor in C++). The '+' method must evidently create a new instance of MyInteger for its return value, just like 'image' must create a new string instance. >I declare the following variable and initialize it > > V:roman := make a roman with the value 5 > >I have two questions: > >(a) what should (V+V).image yield? "10" or "X"? > (V+1).image "6" or "VI"? > (1+V).image "6" or "VI" or error (in +)? > >(b) what do various object oriented systems actually do? > > >If V+V is not a roman (but an integer, 10) then some >information has been lost. This might be reasonable but it >does seem surprising. (b) Because we need the user-defined class MyInteger, _both_ 'V+1' and '1+V' will in most languages cause an error (at compile or run time depending on whether the language is statically typed or not). The integer '1' must therefore first be converted into a MyInteger. However, at least C++ will do automatic conversions if appropriate conversion operators have been defined. (a) Since you do not override '+' but inherit the superclass method, which returns a MyInteger, you will get the first alternative in all cases. If you do redefine '+' in Roman to yield a Roman result (with a MyInteger second operand) you will get the second alternative except in the last case. (In C++ however, if '+' is _virtual_ in MyInteger, you are not allowed to change the result class in the overriding method.) In C++ you can actually define distinct methods for each of the three above operand type pairs and give each of them exactly the result type that you like, independently. The appropriate method will then be selected at compile time; so if you use pointers to objects, the actual run-time class of the objects pointed to has no effect. - In CLOS, the "multi-method" principle means that you can also define different methods for different type pairs, but the selection will happen at run time based on the actual classes of the objects. By suitably defining several >Stephen Adams S.Adams@uk.ac.soton.ecs (JANET) >Computer Science S.Adams@ecs.soton.ac.uk (Bitnet) >Southampton S09 5NH, UK S.Adams@sot-ecs.uucp (uucp) It really wasn't too naive at all! Markku Sakkinen Department of Computer Science University of Jyvaskyla (a's with umlauts) Seminaarinkatu 15 SF-40100 Jyvaskyla (umlauts again) Finland SAKKINEN@FINJYU.bitnet (alternative network address)