This post originated from an RSS feed registered with Agile Buzz
by James Robertson.
Original Post: Describing Smalltalk
Feed Title: Cincom Smalltalk Blog - Smalltalk with Rants
Feed URL: http://www.cincomsmalltalk.com/rssBlog/rssBlogView.xml
Feed Description: James Robertson comments on Cincom Smalltalk, the Smalltalk development community, and IT trends and issues in general.
In an article titled "Java's new considered harmful", Doctor Dobbs describes Smalltalk:
The best example is an instance-controlled class, where the class writer wishes to restrict the number of instances. When the maximum number of instances is one, you have the Singleton pattern (described in Design Patterns by Erich Gamma et al., Addison-Wesley, 1995). Singleton is often used when the object corresponds to a unique item in the real world (such as the keyboard or computer itself), or when the object is the sole manager for some resource. Java's Runtime class is an example of the latter: Its single instance manages interactions between the Java virtual machine and native operating system.
In Smalltalk, simply override #new in your class, and have it hand back (or create if it's not there yet) the sole instance.
Sometimes only a few instances of a class are desired. Imagine a class representing ASCII characters. There are only 256 of those. If the class is immutable and doesn't carry any other information, only 256 instances of the class need ever exist--more would just clutter memory. For a more dramatic example, consider the Boolean class: Only two instances are ever necessary, one for True and one for False. In addition to saving memory, having only one instance per value also allows testing for equality using the "==" operator, instead of the slower "equals" method.
In Smalltalk, there are sole instance of True and False. Yes, there's VM support for that, but you can get the same effect in user code by overriding #new and #basicNew to not allow the creation of new instances.
For a more sophisticated and (currently) hypothetical example, consider the Integer class. There are many possible instances of this class -- too many to cache them all -- but we might conjecture that some values are more common than others. Probably Integer objects representing the numbers from -2 to 100 are more likely to occur than others. A clever implementation could cache objects for these numbers, saving the time and storage involved in their creation.
Heh. Smalltalk does this, with class SmallInteger. It's an optimization for smaller (2^^29-1) integers, with auto-promotion when you exceed that range. The article also points out the non-polymorphic nature of new(), and the various work-arounds used to deal with that. In Smalltalk, #new is just a method. Override it to your heart's content.
Nearly all the way down, the author gets to the nub of the matter - in Smalltalk, these problems simply don't exist:
In Smalltalk, where dynamic typing makes downcasting unnecessary and exceptions are not treated as rigorously as Java, class-based creation is convenient, elegant, and polymorphic (see SmallTalk-80: The Language and Its Implementation, by Adele Goldberg and David Robson, Addison-Wesley, 1983). In fact, it is the usual way to create objects in that language.
He describes all that a bit further down, and points to what he thinks is a flaw:
Smalltalk uses the class-based approach to creation. There is an object corresponding to each class, and instances are created by sending a new message to the class object. This is elegant and polymorphic. Indeed, it is common in Smalltalk programs to pass around a class object when polymorphic creation is required. But Smalltalk's mechanism suffers from a serious drawback: Initialization is not enforced. new creates objects but does not initialize them. The convention is to have an initialize method for each class that is called after new, but you can forget to call initialize, leaving the object in an invalid state. Why not combine creation and initialization by calling initialize from within new? Because new is polymorphic, so it must always take the same number of arguments (namely zero), whereas each class may require a different number of arguments for initialization.
Well, you aren't limited to #new. You can create your own class side creation methods (example: Point x: xVal y: yVal). As to initialization, I've had plenty of cases where I've not wanted my new object initialized, or initialized in non-default ways, so whether this is a flaw or a feature is a matter of opinion. I'm used to it, so I could easily be biased in the matter. Also, a new object wil all instance variables set to nil may not be invalid - that may well be the right starting state. It all depends on the use case.
In any event, it's a good article, and explores the problem. Read it yourself, and see what you think.