Objects, classes, and constructors are an interesting thing in Smalltalk. Coming from languages like C#, Visual Basic, or Java, one expects to be able to declare constructors in your classes. You also expect them to be “special” nameless methods that can only be called by the “new” keyword when creating instances of your class. Smalltalk is different, and better, or worse, depending on your point of view.
Smalltalk is a language that “allows” one to write great code. It never feels like it gets in your way, however many things in Smalltalk are done by convention only, so it won’t “force” you to write great code.
Constructors in Smalltalk are simply a convention; the language has no “new” keyword. In Smalltalk, your classes themselves are objects, singletons in fact; they are the only instance of their meta class. This might sound weird, so lets look at an example. Say we declare a Person class
Object subclass: #Person
instanceVariableNames: 'firstName lastName'
category: 'OnSmalltalk'
First, notice that this is simply a method call on the object class (there is no special syntax for creating classes), which itself is an object. This creates two classes in the runtime image, one called “Person”, and one called “Person class”. The class “Person” is the sole instance of the class “Person class”. “Person class” is an instance of the class “Metaclass”.
So in Smalltalk for every class you create, an invisible parallel hierarchy of meta-classes is created. These meta-classes are referred to as the “class side” by Smalltalkers, and by the Smalltalk code browser.
The reason I mention all this is because these meta-classes commonly show up in other languages as the “Factory” pattern, a pattern all about object construction. This is important because it’s a great way to conceptualize the meta class, it’s the factory for creating instances of the class. To create an instance of our #Person, we do this…
person := Person new.
Notice, #new is a method on the “Person” class, rather than a keyword in the language. It’s simply an ordinary method that happens to be named #new. Unlike other languages, constructors in Smalltalk are nothing special, they’re simply any method that happens to create and return an instance of a class. Now, we could do this…
person := (Person new)
firstName: 'Ramon';
lastName: 'Leon';
yourself.
But a constructor would really help pretty this up and encapsulate the knowledge about what fields are required for construction rather that forcing the client to individually initialize the object and hoping he does it correctly. So let’s write a constructor for #Person, we’ll put it on the “Person class”, or the Person’s class side as it’d normally be called.
Person class>>firstName: aFirstName lastName: aLastName
^(self new)
firstName: aFirstName ;
lastName: aLastName;
yourself.
Notice this is simply an ordinary method named #firstName:lastName on the Person’s meta class. It’s pretty much the same pattern as before, but calls “self new”, the default constructor inherited from its superclass. I can say self because this method is in the “Person class” It can be used like so…
person := Person firstName: 'Ramon' lastName: 'Leon'.
Much nicer now, a client no longer needs to know what arguments to initialize, he can simply call a constructor, more importantly, a named constructor, not an anonymous one like you’d see in most other languages. Consider the advantages of named constructors with an overly simplistic example (ignoring currency)…
someMoney := (Money dollars: 5) + (Money cents: 5).
Of course any real Smalltalk’er would do this by adding a few extension methods to a few Number classes and writing this instead…
someMoney := 5 dollars + 5 cents.
Also unlike “most” other languages, constructors, being ordinary methods in Smalltalk, can be inherited and overridden so subclasses need not redeclare the constructors of superclasses like C# and Java require.
Constructors are put into the method category “instance creation”. Finding constructors for a class is a simple matter of looking at the class side of any class, and looking in this category. If you find a constructor you want to use, highlight it, and press alt+n to see a list of all senders of this method, i.e. instant sample code.
On the instance side of a class, I could, if necessary, override #initialize which is automatically called by the default #new constructor. This is useful when you want to initialize your instance variables on object creation rather than lazily. For example…
Person>>initialize
super initialize.
relatives := Set new.
Some Smalltalk’ers prefer to write their constructors in a different style, one that enforces encapsulation a bit more, by not allowing public setters for all the instance variables, like so…
Person class>>firstName: aFirstName lastName: aLastName
^(self new)
initializeFirstName: aFirstName lastName: aLastName;
yourself.
Person>>initializeFirstName: aFirstName lastName: aLastName
firstName := aFirstName.
lastName := aLastName.
relatives := Set new.
Personally, I don’t prefer this style, because it feels a bit repetitive creating essentially two constructors to avoid having public setters for your instance variables. This style feels like the author doesn’t trust me to not abuse the class, which doesn’t to me, feel like the Smalltalk spirit. It is however, in common use and you’ll see plenty of both of these styles in other peoples code.
Often, while growing a program, one will start without any constructors, doing inline cascaded initialization and only after using the class a bit, will you refactor a few examples into cleaner code using constructors.
To conclude, I hope you’ll notice from the sample code shown so far, everything is done using only objects, their instances, and their methods. There is no special syntax or keywords for creating classes or their constructors. In fact, there are only 6 reserved keywords in the entire Smalltalk language, self, super, nil, true, false, and thisContext. By comparison, Ruby has 38, Java has 52, C# about 76.
This should underline just how much more Smalltalk relies on pure OO and message passing rather than special language constructs. By being minimalist and only providing syntax for assignment, message passing, method return, and a few special literal notations for things like strings, arrays, numbers, and blocks, Smalltalk can be any language you want it to be. All of Smalltalk’s control and iteration structures are implemented in the library, as ordinary objects with ordinary methods. There’s simply no need for so many reserved words.
Smalltalk is not so much a language, as an extensible notation for creating languages. To rip off a famed martial artist, empty your mind, be formless, shapeless, like Smalltalk. If you put Smalltalk into a financial application, it becomes a custom finance language. You put Smalltalk into a shipping application, and it becomes a custom shipping language. Be Smalltalk my friend.
Oh, and to be fair, Smalltalk isn’t the only language with this quality, but it’s certainly my favorite. Languages that lack this quality, as far as I’m concerned, have no real future.
Featured Resources…
The benefits of wireless internet are immense. Nonetheless are the upcoming domain names with a com domain being most sought after. For your domain web hosting, you will be able to get the best and cheap packages, thanks to the rising competition in this sector. With a simple email hosting, options vary. This whole efficient internet system runs on good dedicated servers that keep the ball rolling in the right direction.
Tags: Ruby, Smalltalk