Everybody, sooner or later, looks for the implementation of the
#new method in Object class. To their surprise, they
don’t find it; if they’re really smart, they search for implementors
of #new in the image and they find out it is implemented by
Behavior... which turns out to be a subclass of Object! The
truth starts showing to their eyes about that sentence that everybody
says but few people understand: “classes are objects”.
Huh? Classes are objects?!? Let me explain.
Open up an image; then type the text following the
st> Set superclass! HashedCollection st> HashedCollection superclass! Collection st> Collection superclass! Object st> Object superclass! nil
Nothing new for now. Let’s try something else:
st> #(1 2 3) class! Array st> '123' class! String st> Set class! Set class st> Set class class! Metaclass
You get it, that strange
Set class thing is something
called “a meta-class”... let’s go on:
st> ^Set class superclass! Collection class st> ^Collection class superclass! Object class
You see, there is a sort of ‘parallel’ hierarchy between classes and metaclasses. When you create a class, Smalltalk creates a metaclass; and just like a class describes how methods for its instances work, a metaclass describes how class methods for that same class work.
Set is an instance of the metaclass, so when you invoke
#new class method, you can also say you are invoking
an instance method implemented by
Set class. Simply put,
class methods are a lie: they’re simply instance methods that
are understood by instances of metaclasses.
Now you would expect that
Object class superclass answers
nil class, that is
UndefinedObject. Yet you saw that
#new is not implemented there... let’s try it:
st> ^Object class superclass! Class
Uh?!? Try to read it aloud: the
Object class class inherits
Class is the abstract superclass
of all metaclasses, and provides the logic that allows you to create
classes in the image. But it is not the termination point:
st> ^Class superclass! ClassDescription st> ^ClassDescription superclass! Behavior st> ^Behavior superclass! Object
Class is a subclass of other classes.
Behavior is concrete but lacks the methods
and state that allow classes to have named instance variables,
class comments and more. Its instances are called
light-weight classes because they don’t have separate
metaclasses, instead they all share
Behavior itself as
Behavior superclass we have worked our way up to
class Object again: Object is the superclass of all instances as well
as all metaclasses. This complicated system is extremely powerful,
and allows you to do very interesting things that you probably did
without thinking about it—for example, using methods such as
#shouldNotImplement in class methods.
Now, one final question and one final step: what are metaclasses instances of? The question makes sense: if everything has a class, should not metaclasses have one?
Evaluate the following:
st> meta := Set class st> 0 to: 4 do: [ :i | st> i timesRepeat: [ Transcript space ] st> meta printNl st> meta := meta class st> ] Set class Metaclass Metaclass class Metaclass Metaclass class 0
If you send
#class repeatedly, it seems that you end up
in a loop made of class
Metaclass44 and its
Metaclass class. It looks like class
Metaclass is an instance of an instance of itself.
To understand the role of
Metaclass, it can be useful
to know that the class creation is implemented there.
Think about it.
Random classimplements creation and initialization of its instances’ random number seed; analogously,
Metaclass classimplements creation and initialization of its instances, which are metaclasses.
Metaclassimplements creation and initialization of its instances, which are classes (subclasses of
The circle is closed. In the end, this mechanism implements a clean, elegant and (with some contemplation) understandable facility for self-definition of classes. In other words, it is what allows classes to talk about themselves, posing the foundation for the creation of browsers.
out to be another subclass of