Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!uwm.edu!psuvax1!rutgers!cmcl2!lanl!lambda!jlg From: jlg@lambda.UUCP (Jim Giles) Newsgroups: comp.object Subject: Re: Inheritance explained... finaly... Message-ID: <14189@lambda.UUCP> Date: 10 Jan 90 23:28:37 GMT References: <661@parcplace.com> Lines: 52 From article <661@parcplace.com>, by khaw@parcplace.com (Mike Khaw): > [...] > ParcPlace's implementation of Complex makes use of version 2.5's > exception handling mechanism to raise an exception on attempts to send > comparison messages (e.g., "aComplex < bComplex"). Which is exactly what I was complaining about. Whoever wrote the definition of the Complex class had to redefine the relational operators on them in order to generate these errors. With multiple inheritance, he would not have had to concern himself with such things (which he shouldn't). Complex numbers aren't ordered - so the implementor of them shouldn't have to worry about relational operators AT ALL. > [...] > As for Time and Date, I can imagine wanting to do arithmetic on > instances of them (in fact, I have an old Casio calculator that does > arithmetic on times and dates). Not full arithmetic though. You want to subtract two dates or add a number of days to a date, for example. You probably never want to take the square root of a date or multiply two dates. That's why Time and Date are subclasses of Magnitude but not Number (usually). > [...] > Double dispatching takes care of making binary operations commutative; > e.g., "2 + aComplex" conceptually results in the "+" method in > SmallInteger "failing", then turning things around and sending > "aComplex + self", since the "+" method of Complex implements adding > integers to complex numbers. SmallInteger doesn't have to know > anything about Complex, Float, etc., it just has to know that the > argument to its "+" method is not something that it can handle, and > do the double dispatching. Yes, double dispatching will work for commutative operators. This is an inefficient and clumsy solution which happens to work (and leave _some_ people satisfied). However, a lot of operators aren't commutative. What do you do with "2 / aComplex"? When I added Complex to SmallTalk, it _had_ special cases for Float and Fraction in both the Integer ans SmallInteger classes. I switched it to do double dispatching by defining a new method in the Float, Fraction, and Complex classes called reverseDivide:. So, now when the divide method fails in a given class, I send the reverseDivide: message to the other operand. (So, "2 / aComplex" becomes "aComplex reverseDivide: 2".) This is also inefficient and inelegant. None of this would be required if the arithmetic operators weren't asymetrical in their arguments. As I originally said: the asymetrical nature of message passing is quite appropriate for some data types but not for others. It's unfortunate to be forced to choose instead of being given a language which allows a choice between the two mechanisms. J. Giles