Jump to content

Self (programming language)

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Maury Markowitz (talk | contribs) at 14:39, 26 June 2002 (new article - is the article name right?). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

Self is an object oriented programming language based on the concept of prototypes.

The problem

Traditional object languages, such as Smalltalk, are based on a simple duality. Classes define the basic qualities behaviours of objects, and instances are a particular object based on a class. For instance you might have a "Person" object that has a "name" and the ability to perform "have baby", this is a class. "Bob" is a particular instance of the class Person with the name Bob, and you can ask Bob to "have baby".

This example shows one of the problems with this approach. Bob cannot have a baby, but we've said that any Person can. To "solve" this we need to add a finer level of grainularity in our original design, and have "Male" and "Female" subclasses of Person.

This is, obviously, a contrived (and perhaps in some future, incorrect) example, but this is a very real problem. Unless you can predict with certainty what qualities the objects will have in the distant future, you cannot design your class heirarchy properly. All too often the program will evolve to require additional behaviours, and suddenly the entire system has to be re-designed.

This was in fact not uncommon. Experience with early OO languages like Smalltalk showed that this sort of issue came up time and time again. Systems would tend to grow to a point and then become very ridgid, as the basic classes deep under where the programmer was working were simply "wrong". Without some way of easily changing the original class, you may have a serious problem.

Dynamic languages such as Smalltalk avoided the problem to some degree because the programmer could in fact go in and change the original class. However, doing so was fraught with problems. If you fixed a bug in the library, you might find that some other program stops working as a result.

The solution

The problem here is that there is a duality, classes and instances. Self simply eliminated this duality.

Instead of having an "instance" of an object that is based on some class, in Self you make a copy of an existing object, and change it. So "Female" would be created by making a copy of an existing "Person" object, and then adding the "have baby" method. Basic objects that were used primarily to make copies of were known as prototypes.

This may not sound earth shattering, but in fact it is. If you have to fix a problem in some "base class" because your program has a problem, simply change it and make copies of it instead. No other program will see this. If at some point in the future men can have babies, big deal, add it.

Better yet, this actually dramatically simplifies the entire OO concept as well. Everything might be an object in traditional systems, but there is a very fundamental difference between classes and instances. In Self, there isn't.

The language

Self objects are a collection of "slots". Slots are accessors methods that return values, and placing a colon after the name of a slot sets the value. For instance if you have a slot called "name", "myPerson name" returns the value in name, and "myPerson name:'gizifa'" sets it. Note that there is no distinction in Self between fields and methods, everything is a slot.

The syntax for talking to slots is Smalltalk-like, with "object_name slot_name" pairs being listed from left to right, with the lines end on a period. For instance:

'Hello, World!' print.

Is the Self version of the hello world program. The ' syntax is a shortcut that makes a copy of the known string object and puts "Hello, World!" into its only slot. Grouping is as in math, using parens. For instance:

('Hello, World!' uppercase) print.


A slightly more complex example:

labelWidget clone label: 'Hello, World!'.

makes a copy of the "labelWidget" object with the clone message (no shortcut this time), then sends it a message to put "Hello, World" into the slot called "lable". Now let's do something with it:

(desktop activeWindow) draw: (labelWidget clone label: 'Hello, World!').

In this case the (desktop activeWindow) is performed first, returning the active window from the list of windows that the desktop object knows about. Next (read inner to outer, left to right) the code we examined earlier returns the labelWidget. Finally the widget is sent into the draw slot of the active window.

Inheritance

Every object in Self has a "parent" slot, which contains a pointer to the object it was created from. Any message not handled by a particular object is then sent to its parent. This is how Self handles inheritance, based on a delegation style. Consider the meaning of:

myObject parent: someOtherObject

This is quite interesting, it changes the "class" at runtime.

[need examples of how to make a new "class" using the cloning operations]