Classes and Prototypes
The most distinct difference between Self and Smalltalk is that Self does not have the notion of Classes. There is no “is an instance of” relation between an object and a class. Self rather has been one of the first prototypical object-oriented language, and in this respect a precursor to JavaScript. Hence, the typical way to create a new object in Smalltalk is instantiation whereas in Self it is cloning.
Execution and Messages
As you already have found out, the second fundamental difference is that in Self, the only notion of execution is the message send, whereas in Smalltalk, assignment and object field access also are present. Furthermore, there is no such thing as global state in Self. You can only access what you can retrieve by sending messages. Self however tracks some “well known objects”, which a newly created object can be given.
State and Slots
Pondering on the two previous points, “No classes” and “only messages”, makes it clear, that the Smalltalk distinction between and objects state and its behavior is not directly present in Self. Where Smalltalk stores state in an objects’s instances variables and behavior in method dictionaries in its class, Self uses the notion of slots, which can represent both state and behavior.
Sharing behavior
To help organizing behavior, Self not only provides prototypes but also traits. A trait is an object that only contains behavior, and which several objects share. (Moreover, there are also mixins, small portions of behavior and state, that can be composed into other objects).
Objects in Self can have parents to which messages are sent that the object itself does not understand (delegation). This creates hierarchies that can be similar to class inheritance in Smalltalk, but does not need classes.
A few Examples
Creating a new object
SmalltalkObject new
Self:
- a plain object:
()
or(||)
(to make the absence of slots explicit) - a copied object:
someObject copy
Creating an object with some fields
SmalltalkObject subclass: #MyObjects instanceVariableNames: 'foo bar'. "…"
MyObject new.
Self
( | foo. bar | )
Making a collection
SmalltalkOrderedCollection new.
Self
list copy.
“Inheritance”
SmalltalkObject subclass: #MyObject. "…"
Self
( | parent* <- list | )
Resources
I suggest reading the bibliography section on the Self webpage.