Main Page | See live article | Alphabetical index

Prototype-based programming

Prototype-orientation, or more commonly, prototype based programming, is a specific style of object-oriented programming. The first example of a prototype based language was Self, work which has been copied in other projects such as Cecil, JavaScript, NewtonScript and the MOO programming language.

Traditional OO

With traditional OO systems, objects come in two general types. Classes organize the basic layout and functionality of other objects, and instances are "usable" objects based on the pattern inside a particular class. Using such a system typically means designing the classes you'll need, and then writing a program that creates various instances of those classes for the user to work with.

If you look inside the computer you can quickly see the reason for this dichotomy. The classes are in fact collections of code for the objects, which is the same for all instances, whereas the instances are collections of memory holding the object's data, which is what really distinguishes them from each other (a concept known as state). This model works well with traditional compilers and languages in general, which basically write code and then have that code manipulate data.

For instance, lets say you're making an address book application that can phone people. You would have a class called Person to hold the list of people. People have names and a phone number. If you were to look at such a program you would find that your Person was represented by a block of memory with the code for dialing the phone, and the various instances (Bob, Mary, etc.) are blocks of memory with a pointer to their class, along with the name and phone number. When you ask the system to phone Bob, it looks up Bob's phone number from the instance data, and then looks up the phone method by following the pointer back to the code in the Person class.

However these systems have a serious problem that is only notable as system size grows. Programs rarely remain static, and invariably the original class structure becomes less useful. That results in more code being added to new classes, which largely negates the value of OO systems.

It would be easier if your program could change the behaviour of these underlying classes, but in most systems they are compiled code that can't be changed.

The prototype

Prototype languages avoid this problem by dispensing with the duality that causes the problem. Instead of data-containing instances and function-containing classes, they just have objects, and nothing but objects.

To make a new object you make a copy of an existing one. All such systems start with at least a single Object loaded up, but they all have a list of common objects to work from which makes it more like a traditional system. When you copy an object you get an entirely new one that starts with the same default behaviours as it's original. Instead of having a pointer to a class, this new object contains a pointer to the object that created it.

In fact the new object is largely empty. It will only start growing in memory if and when the program changes it. This is quite different than a traditional OO system, where every instance of a class always sets aside a known amount of memory. Here the basic object consists of only one pointer.

Additional data can be added to any object at any time. If you want your new Person to have a name of "Bob", just go ahead and add it. The object will, at that point, grow to hold the new data as needed.

This is a very important distinction with conventional languages. Since the objects grow as needed, you can add anything to any object. Want Bob's object to have a "cell phone"? Go ahead. Mary has a "fax number"? Fine. In fact every object in such a system tends to be different than every other, not only in the data itself, but in what data is being recorded.

Its also important to consider that the same sort of "add anything" rule applies to methods as well as data. If your Mary object needs a new method that no one else needs, say "send fax", you can add that method using the same methodology. For this reason most prototype based languages refer to both data and methods as "slots".

Prototype based languages tend to start with a selection of basic objects that you can make copies of. In general these objects tend to have method definitions only, relying on the programmer to add the data as needed. For instance, a Point object that can record positions on the screen might contain methods for adding and subtracting points, but it wouldn't in fact include the x and y definitions – that would be up to the programmer to add to the individual point objects they copy.

All of this results in a tremendous amount of flexibility. Bugs in existing object methods can be fixed as easily as sending the new code (in the form of blocks) into the appropriate "slot". You can turn any object into one that handles remote invocation by replacing methods in the same fashion. Class design becomes a much simpler task, notably because you can easily change the "class" definitions at any point in time, and more importantly, within any application (ie, one app can fix bugs in Object and no one else will see this change).