CSE 505 Lecture Notes:

Metaclasses

October 31, 1994


Class-based languages

In Simula, new objects are created using the "new" procedure, e.g. P :- NEW POINT(10,20); Classes are not runtime objects in Simula! For example, you can't pass a class as a parameter to a procedure, or assign it to a variable.

In Smalltalk-72, classes were runtime objects, but they were rather special. They weren't instances of some class themselves. Also if you just mentioned the name, it would create an instance:

p := Point. (This isn't Smalltalk-72 syntax ... Smalltalk-72 had a hand symbol for quoting, a left arrow for assignment, and other cool non-ascii characters.)

In Smalltalk-76, classes are again runtime objects, but they are made part of the normal class-instance scheme. To make an uninitialized instance of the class Point:

p := Point new. p understands messages like "+" and "x" and "printOn:" The definitions of these are in the class Point, which is itself an object (or in a superclass of points).

Rule: to look up a message name, look in your class. If it's there, use it; otherwise search up the superclass chain. In other words, go up exactly one instance link, and then up 0 or more superclass links.

What is the class Point? In Smalltalk-76 it is an instance of the class Class. Class is a subclass of Object, and an instance of itself. Class understands messages like "new", "instvars", and "compile:" Consequence: all classes understand the same messages!

Thus in Smalltalk-76 initialization must be done like this:

p := Point new. p x: 10 y: 20. or p := Point new x: 10 y: 20.

Metaclasses

In Smalltalk-80, the designers wanted to allow class-specific initialization messages, e.g.

p := Point x: 10 y: 20. To accomplish this, every class is an instance of a unique metaclass. "Point" is an instance of "Point class" (the metaclass for point). Point class defines messages such as x:y:. Another benefit of this is that it gives the programmer a place to hang constants and such, e.g. Float pi

In the Smalltalk environment, the class/instance switch in the browser lets one switch between methods the instances understand and methods the class understand (i.e. methods defined in the class and methods defined in the metaclass).

The cost in confusion is huge, though. A particular problem is that new programmers are hit over the head with this right away (unless the teacher glosses over it, which is the usual response).

Alternative 1: back to Smalltalk-76 (c.f. DeltaTalk)

Alternative 2: CLOS style instance creation:

(make-instance 'point :x 10 :y 20) CLOS has a facility to bundle up keyword-argument pairs and pass them along as arguments for another message. After make-instance creates the new instance, it calls the function initialize-instance with the new instance and the keyword-argument pairs. For example, after make-instance creates a new point (say p), it evalutes (initialize-instance p :x 10 :y 20) (CLOS has even more strange and bizarre meta-mumble stuff than does Smalltalk, but you arguably don't need to know about it as soon.)

Alternative 3: prototype-based system (see Lecture notes on prototypes)

another use of metaclasses: reflective programming see e.g. "The Art of the Metaobject Protocol"

metaobject protocol in CLOS: "an interface to the language that gives users the ability to incrementally modify the language's behavior and implementation, as well as the ability to write programs within the language"

example of use in CLOS: overriding the way instances are stored -- for example, record-like structure vs. dictionary.