Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Self (programming language)
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== Description == Self objects are a collection of "slots". Slots are accessor methods that return values, and placing a colon after the name of a slot sets the value. For example, for a slot called "name", <syntaxhighlight lang="smalltalk">myPerson name</syntaxhighlight> returns the value in name, and <syntaxhighlight lang="smalltalk">myPerson name:'foo'</syntaxhighlight> sets it. Self, like Smalltalk, uses ''blocks'' for flow control and other duties. Methods are objects containing code in addition to slots (which they use for arguments and temporary values), and can be placed in a Self slot just like any other object: a number for example. The syntax remains the same in either case. Note that there is no distinction in Self between fields and methods: everything is a slot. Since accessing slots via messages forms the majority of the syntax in Self, many messages are sent to "self", and the "self" can be left off (hence the name). === Basic syntax === The syntax for accessing slots is similar to that of Smalltalk. Three kinds of messages are available: ;unary : <code>''receiver'' slot_name</code> ;binary : <code>''receiver'' + ''argument''</code> ;keyword : <code>''receiver'' keyword: ''arg1'' With: ''arg2''</code> All messages return results, so the receiver (if present) and arguments can be themselves the result of other messages. Following a message by a period means Self will discard the returned value. For example: <syntaxhighlight lang="smalltalk">'Hello, World!' print.</syntaxhighlight> This is the Self version of the [["Hello, World!" program]]. The <code>'</code> syntax indicates a literal string object. Other literals include numbers, blocks and general objects. Grouping can be forced by using parentheses. In the absence of explicit grouping, the unary messages are considered to have the highest precedence followed by binary (grouping left to right) and the keywords having the lowest. The use of keywords for assignment would lead to some extra parenthesis where expressions also had keyword messages, so to avoid that Self requires that the first part of a keyword message selector start with a lowercase letter, and subsequent parts start with an uppercase letter. <syntaxhighlight lang="smalltalk">valid: base bottom between: ligature bottom + height And: base top / scale factor.</syntaxhighlight> can be parsed unambiguously, and means the same as: <syntaxhighlight lang="smalltalk">valid: ((base bottom) between: ((ligature bottom) + height) And: ((base top) / (scale factor))).</syntaxhighlight> In Smalltalk-80, the same expression would be written as: <syntaxhighlight lang="smalltalk">valid := self base bottom between: self ligature bottom + self height and: self base top / self scale factor.</syntaxhighlight> assuming <code>base</code>, <code>ligature</code>, <code>height</code> and <code>scale</code> were not [[instance variable]]s of <code>self</code> but were, in fact, methods. === Making new objects === Consider a slightly more complex example: <syntaxhighlight lang="smalltalk">labelWidget copy label: 'Hello, World!'.</syntaxhighlight> makes a copy of the "labelWidget" object with the copy message (no shortcut this time), then sends it a message to put "Hello, World" into the slot called "label". Now to do something with it: <syntaxhighlight lang="smalltalk">(desktop activeWindow) draw: (labelWidget copy label: 'Hello, World!').</syntaxhighlight> In this case the <code>(desktop activeWindow)</code> 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. === Delegation === {{main|Delegation (object-oriented programming)}} In theory, every Self object is a stand-alone entity. Self has neither classes nor meta-classes. Changes to a particular object do not affect any other, but in some cases it is desirable if they did. Normally an object can understand only messages corresponding to its local slots, but by having one or more slots indicating ''parent'' objects, an object can '''delegate''' any message it does not understand itself to the parent object. Any slot can be made a parent pointer by adding an asterisk as a suffix. In this way Self handles duties that would use [[inheritance (object-oriented programming)|inheritance]] in class-based languages. Delegation can also be used to implement features such as [[namespace]]s and [[lexical scoping]]. For example, suppose an object is defined called "bank account", that is used in a simple bookkeeping application. Usually, this object would be created with the methods inside, perhaps "deposit" and "withdraw", and any data slots needed by them. This is a prototype, which is only special in the way it is used since it also happens to be a fully functional bank account. ===Traits=== Making a clone of this object for "Bob's account" will create a new object which starts out exactly like the prototype. In this case we have copied the slots including the methods and any data. However a more common solution is to first make a more simple object called a [[trait (computer programming)|traits object]] which contains the items that one would normally associate with a class. In this example the "bank account" object would not have the deposit and withdraw method, but would have as a parent an object that did. In this way many copies of the bank account object can be made, but we can still change the behaviour of them all by changing the slots in that root object. How is this any different from a traditional class? Well consider the meaning of: <syntaxhighlight lang="smalltalk">myObject parent: someOtherObject.</syntaxhighlight> This excerpt changes the "class" of myObject at runtime by changing the value associated with the 'parent*' slot (the asterisk is part of the slot name, but not the corresponding messages). Unlike with inheritance or lexical scoping, the delegate object can be modified at runtime. === Adding slots === Objects in Self can be modified to include additional slots. This can be done using the graphical programming environment, or with the primitive '_AddSlots:'. A '''primitive''' has the same syntax as a normal keyword message, but its name starts with the underscore character. The _AddSlots primitive should be avoided because it is a left over from early implementations. However, we will show it in the example below because it makes the code shorter. An earlier example was about refactoring a simple class called Vehicle in order to be able to differentiate the behaviour between cars and trucks. In Self one would accomplish this with something like this: <syntaxhighlight lang="smalltalk">_AddSlots: (| vehicle <- (|parent* = traits clonable|) |).</syntaxhighlight> Since the receiver of the '_AddSlots:' primitive isn't indicated, it is "self". In the case of expressions typed at the prompt, that is an object called the "lobby". The argument for '_AddSlots:' is the object whose slots will be copied over to the receiver. In this case it is a literal object with exactly one slot. The slot's name is 'vehicle' and its value is another literal object. The "<-" notation implies a second slot called 'vehicle:' which can be used to change the first slot's value. The "=" indicates a constant slot, so there is no corresponding 'parent:'. The literal object that is the initial value of 'vehicle' includes a single slot so it can understand messages related to cloning. A truly empty object, indicated as (| |) or more simply as (), cannot receive any messages at all. <syntaxhighlight lang="smalltalk">vehicle _AddSlots: (| name <- 'automobile'|).</syntaxhighlight> Here the receiver is the previous object, which now will include 'name' and 'name:' slots in addition to 'parent*'. <syntaxhighlight lang="smalltalk">_AddSlots: (| sportsCar <- vehicle copy |). sportsCar _AddSlots: (| driveToWork = (''some code, this is a method'') |).</syntaxhighlight> Though previously 'vehicle' and 'sportsCar' were exactly alike, now the latter includes a new slot with a method that the original doesn't have. Methods can only be included in constant slots. <syntaxhighlight lang="smalltalk">_AddSlots: (| porsche911 <- sportsCar copy |). porsche911 name:'Bobs Porsche'.</syntaxhighlight> The new object 'porsche911' started out exactly like 'sportsCar', but the last message changed the value of its 'name' slot. Note that both still have exactly the same slots even though one of them has a different value.
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)