Cliff Hacks Things.

Tuesday, February 07, 2006

Prototypes and Classes

Class- and Prototype-based OO languages are equivalent. I don't just mean equivalent like any two Turing-complete systems — they're equivalent through a simple transformation, like tail recursion and iteration.

Prototype-based languages are distinguished by the fact that objects can have their own unique behavior and structure. You can add a method or slot to an individual object instance, rather than having to modify some class that defined it. (The benefits in UI programming are obvious — hint: no more action listeners, just redefine a method on that particular button.)

Under the hood, however, prototype-based runtimes usually have behavior objects that back the object instances. An instance will contain some number of data slots, and a reference to its behavior, where the actual methods are stored, along with references to its delegates (similar to parent-types in class-based languages). Multiple instances can share a single behavior object, which dramatically reduces memory requirements.

Now, the methods are stored on the behavior, which may be shared by many instances, but you can still add a method to a particular instance — because the behavior is copy-on-write. When you add a slot or a method to an instance with a shared behavior, it creates a new behavior containing your modification, which delegates back to (read: inherits from) the original. The modified instance is switched to use the new behavior, and voila.

This preserves the prototype semantics of the language, while reducing memory footprint and improving cache performance.

It also looks a lot like a class-based object system — and, in fact, a sufficiently flexible class-based object system can achieve exactly the same behavior.

Translating from the prototype world to the class world, adding a method or slot to an instance creates a new class (behavior) containing the new method/slot, inheriting from (delegating to) the original class, and changes the instance's class to the new subtype.

Very few class-based object systems are this flexible — Java, for example, cannot change the class of an object on the fly. (In fact, only Smalltalk and Ruby spring to mind, though I'm sure someone will pipe up and insist it can be done in CLOS.) I'd like to see this sort of thing become widely available; I'm not a fan of prototype-based languages in general, but this would be a very powerful feature in a class-based language.


Post a Comment

<< Home