johnson@p.cs.uiuc.edu (01/09/90)
I'm always happy to see a long article from Ed Berard, and this one is no exception. However, there were quite a few things that I disagreed with in this article. First, a matter of history. Simula was the first OOP language. It is true that Smalltalk advanced the state of the art quite a bit, and that most Americans learned of OOP because of Smalltalk, and that Smalltalk is quite a bit different from Simula. However, we should keep our history straight. In my opinion, the three major characteristics of an OOP language are 1. data abstraction 2. inheritance 3. polymorphism caused by late-binding of procedure calls I've never been able to understand why information hiding isn't just an aspect of data abstraction. I also think that data abstraction and abstract data types are synonyms, but maybe I'm just stupid. Note that 3) is broad enough to encompass CLOS generic functions and C++ virtual functions, and that class are nowhere mentioned. Ada falls down on both 2) and 3), because overloading is NOT late-binding nor, in my opinion, true polymorphism. I also take issue with the claim that Smalltalk is less polymorphic than ML. If you have a type system for Smalltalk, which I do, then you will see that Smalltalk programs can do all the tricks of ML, and then a bunch more. In fact, languages like Eiffel or Trellis/Owl have type systems that are as polymorphic as ML. The thing that is so great about ML is that it has a complete type inference algorithm, not that it is the end-all and be-all of polymorphism. In my opinion, type-checking is completely orthoganal to whether a language is OOP or not, and adding type-checking to Smalltalk does not make it more of an OOP language. Snorri Agnarsson said some good things about automatic memory management, all of which I support. It might be possible to think that he implied that memory management is a feature of object-oriented programming. Someone famous in the Smalltalk community (Dan Ingalls?) said this. However, I don't agree at all. Automatic garbage collection is wonderful, and it is especially useful in writing reusable code, but it is orthoganal to OOP. I also agree with the claim that Snorri (or someone else) made that late-binding is more important than inheritance. I think I've said that in public before. Of course, I wouldn't want to give up inheritance. If anybody wants a reference to my definition of OOP languages, I gave it in "Designing Reusable Classes" with Brian Foote in the 2 issue of the Journal of Object-Oriented Programming. (The June/July 88 issue, I think). I'll send copies of the paper to people who can't find copies of the journal. Ralph Johnson -- University of Illinois at Urbana-Champaign
susser@apple.com (Joshua Susser) (01/10/90)
In article <135300019@p.cs.uiuc.edu> johnson@p.cs.uiuc.edu writes: > In my opinion, the three major characteristics of an OOP language are > > 1. data abstraction > 2. inheritance > 3. polymorphism caused by late-binding of procedure calls > ... > Snorri Agnarsson said some good things about automatic memory management, > all of which I support. It might be possible to think that he implied that > memory management is a feature of object-oriented programming. Someone > famous in the Smalltalk community (Dan Ingalls?) said this. However, I > don't agree at all. Automatic garbage collection is wonderful, and it > is especially useful in writing reusable code, but it is orthoganal to > OOP. Not quite. Characteristic 1) (which I generally refer to as encapsulation) implies garbage collection in a rather straightforward manner. Since an object encapsulates its state, once you give it a reference to another object, say as an argument to a message, you have no way of knowing whether that reference is maintained or not. From then on you can never externally know if it is okay to free the referenced (second) object. And if that object is ever referenced by more than one object, you have to be able to look inside all possible referents to know if the object can be reclaimed. The general case of this is called garbage collection. Joshua Susser Apple Computer ,Inc. Object Percussionist Advanced Technology Group arpa: susser@apple.com 20525 Mariani Ave. MS 76-2D uucp: {backbone}!apple!susser Cupertino, CA 95014 ALink: susser.j 408/974-6997 "I beat on objects."
pallas@Neon.Stanford.EDU (Joe Pallas) (01/10/90)
In article <135300019@p.cs.uiuc.edu> johnson@p.cs.uiuc.edu writes: >In my opinion, the three major characteristics of an OOP language are >1. data abstraction >2. inheritance >3. polymorphism caused by late-binding of procedure calls Okay, that looks like a subset of my list, which appears below. >I've never been able to understand why information hiding isn't just >an aspect of data abstraction. I think this is a common point of miscommunication. Many people (perhaps most) treat protection or privacy as part of data abstraction. I prefer to make a distinction between abstraction as voluntary and protection or privacy as involuntary. For example, it isn't hard to do data abstraction in C using structs, but it is impossible to enforce protection. Likewise, in Ada, you can choose whether or not your data type is private, but your client can choose to treat it abstractly even if it isn't private. >I also think that data abstraction >and abstract data types are synonyms, but maybe I'm just stupid. This may not be presented very well, but here's my view on that (and my list): 1) Data abstraction is a property of a language, abstract data types are things in the language/implementation. 2) Protection is a property of a language, messages are things in the language/implementation. (in my view, messages are things which explicitly cross protection boundaries, like protected procedure calls) 3) Bundling code and data together is a property of a language, objects are things in the language/implementation. 4) Universal polymorphism is a property of a language, run-time types are things in the language/implementation. 5) Inheritance is a property of a language, inheritance hierarchies are things in the language/implementation. As far as the list itself goes, many people combine (1) and (2). Various people call (2) or (3) or both ``encapsulation'', so I have given up on that word. Some people feel (5) is not necessary; I believe that (4) without (5) is not very useful. I'd be interested in comments on either my property-of/thing-in approach or the list itself. joe
johnson@p.cs.uiuc.edu (01/15/90)
Markku Sakkinen wrote: >Question: However, isn't it actually bogus that all fundamental things >in _Smalltalk_ are first-class objects? For instance, how do you define >a use a meaningful subclass of SmallInteger, adding at least one >instance variable? SmallIntegers are implemented by a hack (use of a tag bit) so, as far as I know, none of the Smalltalks let you subclass SmallInteger. However, this is not a problem in practice, since it is easy to subclass Integer, and all you have to do is make a new kind of Integer whose value is a SmallInteger and that delegates a few important operations (+,-,/,*,<,=) to its value. Such a subclass will work like a SmallInteger and you can easily add new methods or variables to it without interfering with regular SmallIntegers. This is an extreme example of a general property of inheritance: it is usually a lot cleaner to inherit from abstract classes than from concrete classes. It is quite common for a subclass to need a different data representation, but inheritance brings along the superclass's data representation. Ralph Johnson
sakkinen@tukki.jyu.fi (Markku Sakkinen) (01/15/90)
In article <135300024@p.cs.uiuc.edu> johnson@p.cs.uiuc.edu writes: > >Markku Sakkinen wrote: >>Question: However, isn't it actually bogus that all fundamental things >>in _Smalltalk_ are first-class objects? For instance, how do you define >>a use a meaningful subclass of SmallInteger, adding at least one >>instance variable? > >SmallIntegers are implemented by a hack (use of a tag bit) so, as far as >I know, none of the Smalltalks let you subclass SmallInteger. However, >this is not a problem in practice, since it is easy to subclass Integer, >and all you have to do is make a new kind of Integer whose value is a >SmallInteger and that delegates a few important operations (+,-,/,*,<,=) >to its value. Such a subclass will work like a SmallInteger and you can >easily add new methods or variables to it without interfering with >regular SmallIntegers. > >This is an extreme example of a general property of inheritance: it is >usually a lot cleaner to inherit from abstract classes than from concrete >classes. It is quite common for a subclass to need a different data >representation, but inheritance brings along the superclass's data >representation. Thank you for the information. However, the main reason why instances of the basic atomic classes of Smalltalk don't look like first-class objects to me is that they are immutable (while instances of normal classes are mutable) and they can be neither created (thus there can be no initialisation methods) nor deleted, at least conceptually. In contrast, if the programmer defines a subclass, say MyInteger (concrete), of the abstract class Integer, then instances of MyInteger are entirely ordinary objects; they will obey "reference semantics" instead of the "value semantics" of built-in integer types. As an example, suppose some method of class Car contains price <- anotherCar price If the price object is a MyInteger, this assignment will cause sharing, quite unlike ordinary integers. So it seems unwise to define any subclasses of Integer and similar built-in classes: they might cause unpleasant surprises to users later. This holds for type-checking derivatives of Smalltalk (see e.g. Johnson's paper from OOPSLA'86) as well, since MyInteger _is_ formally a subclass of Integer. Disclaimer (again): because of no practical experience with Smalltalk, the above may be incorrect in technical details. Markku Sakkinen Department of Computer Science University of Jyvaskyla (a's with umlauts) Seminaarinkatu 15 SF-40100 Jyvaskyla (umlauts again) Finland
pallas@Neon.Stanford.EDU (Joe Pallas) (01/17/90)
In article <2704@tukki.jyu.fi> sakkinen@tukki.jyu.fi (Markku Sakkinen) writes: >However, the main reason why instances >of the basic atomic classes of Smalltalk don't look like first-class objects >to me is that they are immutable (while instances of normal classes >are mutable) ... Instances of ``normal classes'' are only mutable if they have instance variables. Classes with no instance variables (and, hence, immutable instances) may not be common, but they are both possible and useful. (Example: Booleans) >... and they can be neither created (thus there can be no >initialisation methods) nor deleted, at least conceptually. On the contrary, conceptually they are created and deleted [whatever that means with GC] all the time. It's the implementation that does not actually create and destroy them, for efficiency's sake. The implementation can do that precisely because it makes no difference at the user level. As an exercise, try to write a Smalltalk expression (without using explicit identity tests) that will yield different results when a and b are the same instance of such a class and when they are different instances of such a class. It's not hard to see that if there are no instance variables, all instances have the same behavior (excepting explicit identity tests, which most implementations do not allow to be redefined). And, logically, if they always behave the same you can't tell them apart. joe