Classes and Objects
Some people refer to the "Simula school of object orientation," but this expression is quite misleading. Simula is not an object-oriented language, but it's a class-based language. By contrast, Smalltalk is both an object-oriented and a class-based language. Self, a direct descendent of Smalltalk, is object-oriented, but isn't class-based.
In Smalltalk, everything is an object, and objects are instances of classes. When you send a message to an object, its class decides how that message is handled. Because everything is an object, classes are objects, too. Just as an object is an instance of a class, a class is an instance of a metaclass.
In Self, classes didn't enjoy any special status. Every object decided on its own how it handled messages. You could add methods to a single instance of an object. Rather than delegating method lookup to a class (which delegated to its superclass), objects could delegate lookup to any other object, known as its prototype.
Neither of these models is more expressive than the other—it's possible to translate automatically between the two, although running Smalltalk code in a Self virtual machine is easier than the other way around. Effectively, a Smalltalk object is a Self object that doesn't have any methods of its own, and has its class as its prototype.
It works by first observing that, although you can have a different set of methods for every object in Self, people never actually do that. Few objects add methods that aren't present in their prototype. Conceptually, you could implement Self in Smalltalk by making every object an instance of its own class, which inherited from its prototype's class. This technique wouldn't be very efficient, but fortunately it turns out that a lot of these classes will be identical, so you can reuse them. The hidden class transform helps with optimization as well, because you can cache method lookups per class, rather than per object, which gives a much greater change of a cache hit.