jacob@gore.com (Jacob Gore) (01/05/90)
IEEE Spectrum, January 1990. Cover topic: "Technology '90". Under the major heading "Systems software", there is an article called "Object-oriented programming a hit" by Ted G. Lewis ("Expert Opinion"). Here's a passage from it: Perhaps the most powerful concept in object-oriented programming systems is inheritance. Objects can be created by inheriting the properties of other objects, thus removing the need to write any code whatsoever! Suppose, for example, a program is to process complex numbers consisting of real and imaginary parts. In a complex number, the real and imaginary parts behave like real numbers, so all of the operations (+, -, /, *, sqrt, sin, cos, etc.) can be inherited from the class of objects called REAL, instead of having to be written in code. This has major impact on programmer productivity. Sigh... maybe the April 1 issue was published early this year? Jacob -- Jacob Gore Jacob@Gore.Com boulder!gore!jacob
weiner@novavax.UUCP (Bob Weiner) (01/06/90)
In article <1130005@gore.com> jacob@gore.com (Jacob Gore) writes: > IEEE Spectrum, January 1990. Cover topic: "Technology '90". Under the > major heading "Systems software", there is an article called > "Object-oriented programming a hit" by Ted G. Lewis ("Expert Opinion"). > Here's a passage from it: > > Perhaps the most powerful concept in object-oriented > programming systems is inheritance. Objects can be > created by inheriting the properties of other objects, > thus removing the need to write any code whatsoever! > Suppose, for example, a program is to process complex > numbers consisting of real and imaginary parts. In a > complex number, the real and imaginary parts behave like > real numbers, so all of the operations (+, -, /, *, > sqrt, sin, cos, etc.) can be inherited from the class of > objects called REAL, instead of having to be written in > code. This has major impact on programmer productivity. This passage when taken alone (since I have not read the article) indicates that one can operate on 'complex numbers' as if they were 'real's. Try again. I'm sure the intent was to say that the 'real' operators may be used to build the complex operators, which is true. However once again the 'is-a' relation that is so important in many uses of inheritance has been ignored. It's a simple test that can be applied with only a moment's thought: Is a 'complex number' a type of 'real' number? No. It may be composed of a pair of real numbers and hence OO techniques for composition should be applied rather than those for inheritance. With all the good examples in the world of 'is-a' and 'composed-of' relations, why do people continually confuse the relations when programming? -- Bob Weiner, Motorola, Inc., USENET: ...!gatech!uflorida!novavax!weiner (407) 364-2087
jacob@gore.com (Jacob Gore) (01/06/90)
/ comp.object / weiner@novavax.UUCP (Bob Weiner) / Jan 5, 1990 / > This passage when taken alone (since I have not read the article) > indicates that one can operate on 'complex numbers' as if they were > 'real's. [...] I'm sure the intent was to say that the 'real' > operators may be used to build the complex operators, which is true. Unfortunately, that's too generous. The passage I presented is the complete "treatise" of inheritance in the article. Jacob P.S. The rest of the article is quite reasonable. (Half of it does not deal with O-O, but with other productivity improvements -- visualization, CASE, interface building tools, etc.) -- Jacob Gore Jacob@Gore.Com boulder!gore!jacob
jlg@lambda.UUCP (Jim Giles) (01/09/90)
From article <1130005@gore.com>, by jacob@gore.com (Jacob Gore): > IEEE Spectrum, January 1990. Cover topic: "Technology '90". [...] > "Object-oriented programming a hit" by Ted G. Lewis ("Expert Opinion"). > > Suppose, for example, a program is to process complex > numbers consisting of real and imaginary parts. In a > complex number, the real and imaginary parts behave like > real numbers, so all of the operations (+, -, /, *, > sqrt, sin, cos, etc.) can be inherited from the class of > objects called REAL, instead of having to be written in > code. This has major impact on programmer productivity. In fact, I always use Complex numbers to demonstrate the some of the problems which still plague Object-oriented languages. For example, on my SmallTalk system the class heirarchy for numbers is: Object | Magnitude / \ Time Number Date / | \ / | \ Integer | Float Fraction Obviously, I can't make Complex a subclass of number because complex numbers aren't well ordered (and are, therefore, not Magnitudes). Similarly, I can't rearrange the heirarchy an place Magnitude under Number since I don't want the arithemtic operators defined on such things as Time and Date. Some Object-oriented languages are now correcting this problem by allowing multiple inheritance - but not without new problems. Second example: Complex numbers show a weekness in Object-oriented languages with respect to encapsulation. This is because of the concept of 'messages'. For some applications, it is perfectly reasonable (even desireable) to have _functions_ be asymmetrical in their arguments. But, for other applications, it is completely unnatural. In this case, it is necessary to modify the definitions of the Integer, Float, and Fraction classes in order to implement the expected mixed-mode operations on Complex. This violates the spirit of the Object-oriented language with respect to excapsulation. Of course, many Object-oriented languages don't use message passing syntax - and even some that do also offer overloading of operators as a separate mechanism from message passing. It should, after all, be possible to define Complex as a single class without altering any other classes to handle it. In any case, I still have doubts about the future of Object-oriented programming. After all, except for inheritance, the whole concept is a subset of what can be done with generic functions and overloading. Maybe the correct approach is to add inheritance to a language which has generic functions - it can't be THAT hard.
arshad@lfcs.ed.ac.uk (Arshad Mahmood) (01/09/90)
In article <1719@novavax.UUCP> weiner@novavax.UUCP (Bob Weiner) writes: >In article <1130005@gore.com> jacob@gore.com (Jacob Gore) writes: > >This passage when taken alone (since I have not read the article) >indicates that one can operate on 'complex numbers' as if they were >'real's. Try again. You seem to have missed the explanation at the bottom related to April Fools day, even though I suspect the original article seems to be quite serious (self sigh, self sob, etc). A. Mahmood LFCS Edinburgh University Scotland
jgk@osc.COM (Joe Keane) (01/10/90)
In article <14185@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes: >In any case, I still have doubts about the future of Object-oriented >programming. After all, except for inheritance, the whole concept >is a subset of what can be done with generic functions and overloading. >Maybe the correct approach is to add inheritance to a language which >has generic functions - it can't be THAT hard. Mr. Giles has a number of good points. Let me quickly enumerate the bad points of the object-oriented paradigm as it stands today. Type system. Single inheritance completely falls apart once you leave the typical textbook `tree of types' example. Multiple inheritance fixes a number of these problems, but usually complicated things even further. I have yet to see a language which does multiple inheritance cleanly. I can say more about what they do wrong and how to do it right, but that would be a long post. Multiple arguments. Forcing the first (implicit) argument to be special is bogus. This is what you want sometimes, but many operations are fundamentally operations on more than one object. The way you add two numbers in Smalltalk is to construct a message containing one of the numbers as an argument to the addition operator, and send that thing to the other number. I'll let the reader decide if this makes sense, never mind if it is elegant. Also, polymorphism should not be indexed on the class of the first argument. Side effects. Object orientation includes a vague assumption that messages modify their receivers, but not their parameters. This needs to be made more explicit and more general. Note that the C++ `const' keyword is a start, but it only addresses whether you modify the parameters or objects themselves, and not what they may refer to or depend on. Certainly any language which doesn't have a concept of a pure function is deficient. Notably, Smalltalk gets zero out of three on this evaluation. This isn't meant to be critical of the designers of Smalltalk, since you must take into account that it was originally a string pattern matching language, and was created a long time ago before the object-oriented paradigm existed as such. However, i worry when i hear people touting Smalltalk as the state of the art.
khaw@parcplace.com (Mike Khaw) (01/10/90)
jlg@lambda.UUCP (Jim Giles) writes: >In fact, I always use Complex numbers to demonstrate the some of the >problems which still plague Object-oriented languages. >For example, on my SmallTalk system the class heirarchy for numbers >is: > Object > | > Magnitude > / \ > Time Number > Date / | \ > / | \ > Integer | Float > Fraction The current version of ParcPlace's Smalltalk-80 (version 2.5) provides a Complex class as a file-in. The class hierarchy then looks like: Object Magnitude ArithmeticValue Number Fraction Integer LargePositiveInteger LargeNegativeInteger SmallInteger LimitedPrecisionReal Float Point Complex >Obviously, I can't make Complex a subclass of number because complex >numbers aren't well ordered (and are, therefore, not Magnitudes). >Similarly, I can't rearrange the heirarchy an place Magnitude under >Number since I don't want the arithemtic operators defined on such >things as Time and Date. Some Object-oriented languages are now >correcting this problem by allowing multiple inheritance - but not >without new problems. 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"). 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). >Second example: Complex numbers show a weekness in Object-oriented >languages with respect to encapsulation. This is because of the >concept of 'messages'. For some applications, it is perfectly >reasonable (even desireable) to have _functions_ be asymmetrical >in their arguments. But, for other applications, it is completely >unnatural. In this case, it is necessary to modify the definitions >of the Integer, Float, and Fraction classes in order to implement >the expected mixed-mode operations on Complex. This violates the >spirit of the Object-oriented language with respect to excapsulation. >Of course, many Object-oriented languages don't use message passing >syntax - and even some that do also offer overloading of operators >as a separate mechanism from message passing. It should, after all, >be possible to define Complex as a single class without altering >any other classes to handle it. 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. -- Mike Khaw ParcPlace Systems, Inc., 1550 Plymouth St., Mountain View, CA 94043 Domain=khaw@parcplace.com, UUCP=...!{uunet,sun,decwrl}!parcplace!khaw
jlg@lambda.UUCP (Jim Giles) (01/11/90)
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
franka@mentor.com (Frank A. Adrian) (01/11/90)
In article <1831@osc.COM> jgk@osc.COM (Joe Keane) writes: :In article <14185@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes: :>In any case, I still have doubts about the future of Object-oriented :>programming. After all, except for inheritance, the whole concept :>is a subset of what can be done with generic functions and overloading. :>Maybe the correct approach is to add inheritance to a language which :>has generic functions - it can't be THAT hard. : :Mr. Giles has a number of good points. Let me quickly enumerate the bad :points of the object-oriented paradigm as it stands today. : :Type system... :Multiple inheritance fixes a number :of these problems, but usually complicated things even further. I have yet to :see a language which does multiple inheritance cleanly. : :Multiple arguments. Forcing the first (implicit) argument to be special is :bogus... :Polymorphism should not be indexed on the class of the first argument. : :Side effects. Object orientation includes a vague assumption that messages :modify their receivers, but not their parameters. So what's the problem? You have a language that does somewhat better on ALL of these - CLOS. Not only does it have multimethods and generic functions (See Mr. Giles' suggestion and the stuff about multiple arguments), it also has a fairly controllable multiple inheritance system (although I agree, it sometimes isn't exactly clean - is that simply a problem with describing real world multiple roles which objects can play?). Side effects can be performed on message parameters (or not). All in all, it seems like a pretty good language (especially if you like LISP in the first place :-). Just my own somewhat grumpy opinion... Frank A. Adrian Mentor Graphics, Inc. franka@mntgfx.com
johnson@p.cs.uiuc.edu (01/13/90)
>jgl@lambda.UUCP (J. Giles) writes >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. >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. I agree that the asymetrical nature of message passing is not appropriate for all data types, but I disagree with everything else. Double dispatching is actually quite efficient. In my opinion, it is also quite elegant. Moreover, it works best with noncommunitive operators. Double dispatching is a good way to implement those data types that require symetrical method lookup. The major problem with double dispatching in Smalltalk is that the programming environment does not support it. Kurt Hebel and I have a paper in an upcoming issue of JOOP that describes a double dispatching browser that makes it very easy to write code that uses double dispatching. It automatically writes all the little methods for message forwarding, automates inheritance along the lines of the class of the second object, and in general makes the implementation of the arithmetic classes in Smalltalk very symetrical. Kurt completely reimplemented the Smalltalk arithmetic classes, adding matrices, vectors, functions, etc. I like double dispatching because my Smalltalk compiler can produce very efficient code for arithmetic that is implemented using it, but Kurt is very happy with it in Smalltalk-80. The resulting system is very similar to CLOS generic functions from the programmer's point of view. Ralph Johnson
johnson@p.cs.uiuc.edu (01/13/90)
I disagree with almost everything that jgk@osc.COM said in his message. >Type system. He then goes on to talk about inheritance. (I guess that I agree that I have yet to see a language which does multiple inheritance cleanly, though Trellis/Owl is pretty good.) His basic mistake is to confuse inheritance with types. This is understandable, because lots of other people do too. However, the problems with single inheritance that he alludes to are easily fixed by a type conformance algorithm that ignores inheritance. Witness Emerald, which does not have inheritance at all. >Multiple arguments. This is a bogus argument. Double dispatching works fine for those cases where you really want to choose a method based on the class of several objects. Most of the time you don't, and messaging works fine. >Side effects. As a matter of fact, I guess I agree with the basic assumption that it would be good to be able to reason about side effects better, but this is not particularly related to object-oriented programming, either in the need or in the solution. I disagree that object orientation includes a vague assumption that messages modify their receivers, but not their parameters. It is common for Smalltalk methods to change the state of their parameters and also for them to not change any state at all. The statement "Certainly any language which doesn't have a concept of a pure function is deficient" is a little odd, since none of the popular languages support this concept as well as they should. The only language I've seen that lets procedures combine arguments that can be changed with those that cannot in a way that I think is flexible enough is FX. I'd appreciate any other pointers to work in this area. Ralph Johnson