Last updated at 9:56 pm UTC on 13 October 2004
Every class is an instance of a metaclass. Metaclasses are not named. You refer to them by sending the message class to their instance.
So there is for example the class Collection. Its Metaclass is accessed by
[October 04, 2000, John-Reed Maffeo]
Since I am not a Metaclass guru, I will just share some
references that I have collected. Maybe someday I will come
back and write the definitive text (which will in any case
be plagiarized shamelessly from these;)
Smalltalk-80 The Language. Adele Goldberg, David Robson, 1989
Smalltalk, Objects,and Design. ChamondLiu, 1996
Smalltalk: An Introduction to Application Development Using VisualWorks.Trevor Hopkins, 1996
Bryan Murphy-Dye had this to say about Metaclasses:
Our mental picture of a class is that there is one instance for each class. For example, we tend to think there is one instance out there representing the String class, and the browser helps feed this image.
In actuality, there two instances exist for every class: a Metaclass instance and a Class instance. The Metaclass instance contains the class methods and class instance variable names for a class. When you click on the 'class' button in a browser, you are actually looking at the methods from the Metaclass instance. The Class instance contains the methods and variables that belong to the instances of the class. So there are three instances for the string 'abc': the String Metaclass, the String Class, and the instance containing the characters 'abc'.
Class and Metaclass are just like other classes, so each of them also have a Class instance and a Metaclass instance.
There is a little magic that goes on at this point because there is a chicken and egg problem: the 'Class' class can't exist without the Class instance and Class metaclass, yet how can you have a Class instance until the Class class exists? I haven't looked into how Squeak solves this, but 'The Art of Metaobject Protocol' goes into great detail on one way to solve the bootstrapping problem.
In a way there are three levels of definition for every instance in the environment:
- metaclass to hold class method/variable information
- class to hold instance method/variable information
- instance to hold instance data
When you are holding an instance and ask it to evaluate a selector, it determines the code to execute by looking one level higher. For example, '3 + 5' sends #+ to the instance '3'. The #+ selector is looked for one level higher at the class. For '3 class name', #class is sent to '3' which returns the class level (which is the Class instance for SmallInteger). This method happens to return a Class instance. So #name is sent to the next level up: the metaclass level.
You noted that:
'Symbol class inspect' is a Metaclass
Symbol class = Metaclass —-> false
By the same token, note that
'3 class inspect' is a SmallInteger class
3 class = SmallInteger class —-> false
So what shows on the top of the inspector is really one level higher. Try:
Symbol class class = Metaclass —-> true
Hope this helps a little ...