Previous | Table of Contents | Next |
At any time, a variable references a single object. The object that a variable references is called the value of the variable. Unless it is explicitly initialized, a variable initially references the object that is the value of the literal identifier nil. The value of a variable is modified by using the assignment operator. The assignment operator is written as a colon immediately followed by an equal sign (:=). The assignment operator is the only true operator in the Smalltalk language. It replaces the value of the variable to the left of the assignment operator with the value of the expression to the right of the assignment operator. Individual statements in Smalltalk programs are separated using periods. Some examples are listed here:
temp1 := this is a string. temp2 := temp1. both variables now reference the same string object temp1 := nil. restore temp1 to its original value, temp2 still references the string temp1 := temp2 := #(1 2 3 4). multiple assignment
Smalltalk variables store references to objects, not the objects themselves. If the value of one variable is assigned to another variable, then both variables reference the same object. Any change to an objects state made through a reference from a variable is visible through all other variables that reference the same object. Assignment to a variable does not modify the state of the object previously referenced by the variable; it only changes which object the variable references.
Smalltalk variables are untyped. A reference to any object can be assigned to any Smalltalk variable. An individual variable can reference many different types of objects over the course of its existence. The fact that Smalltalk variables are untyped does not mean that Smalltalk is not a type-safe language. Smalltalk is dynamically typed. Whenever an operation is applied to an object, Smalltalk dynamically verifies that the operation is defined for that particular type of object and signals an error condition if it is not.
Any state (data) that a Smalltalk object can store is encapsulated. This means that the data are not directly accessible by those parts of a program that are not directly related to the definition of the object. Generally, a Smalltalk programmer cannot access and thus does not need to be aware of the specific implementation of an objects encapsulated state. An objects behavior is the set of publicly callable operations that are defined for the object. Smalltalk programmers usually characterize an object by its behavior rather than its state. They think about what the object can do, not how its data are structured.
A message is a request to an object to do something. What an object does in response to a message is invoke one of the operations that make up the objects behavior. The majority of code in a Smalltalk program consists of message expressions, which cause messages to be sent to objects. In fact, except for variable assignments, all computations in a Smalltalk program are expressed in terms of message expressions.
A message expression specifies an object that is the receiver of the message, a selector that names the operation to be invoked by the message, and optionally, a set of objects that serve as arguments for the message. Several syntactic variants of message expressions exist, but they all have the same general structure, which reads from left to right as follows:
receiver selector arguments
The objects that serve as the receiver or arguments of a message expression can be identified by variables or literals, or as the value of other message expressions. There are three specific syntactic forms for selectors and three corresponding variants of message expression syntax. The following sections address unary messages, binary messages, and keyword messages.
A unary message expression defines a message that has no arguments. The selector of a unary message is an identifier. Here are some examples of unary expressions:
12345 negated -12345 abc reverse cba #(1 2 3) last 3
A Smalltalk message expression always computes and returns a value as the result of the expression. The value of a message expression is a reference to an object. In these and other examples we use the symbol [special character] on the line following the expression to identify a printable description of the object that is the result of the expression. This is a typographical convention and is not part of the Smalltalk language.
In the first expression, the integer object represented by the literal object 12345 is the receiver of the message. The selector is the identifier negated. The message invokes an operation that computes the negated value of the receiver.
Because message expressions have a value, they can be used to directly specify the receiver (or arguments) of other message expressions. For example, consider these lines:
#(1 2 3) last negated -3
This is a compound message expression consisting of two unary messages. The first message expression sends the message with the selector last to the literal array, and the result is the integer object 3. That object then becomes the receiver of a message whose selector is negated. This message returns -3, which is the value of the compound expression. In general, the individual messages composing a compound sequence of unary messages are evaluated left to right.
In Smalltalk programs, the receiver of a message is most frequently specified using a variable. Hence, an expression such as the one shown previously might actually appear as follows:
list last negated
In this case, the first identifier, list, is a variable, and the remaining two identifiers are selectors. For the most part, this should not be a source of confusion. Simply read expressions from left to right.
The second syntactic form for message expressions is a binary message expression. Each binary message expression has exactly one argument. In standard Smalltalk, the selector of a binary message is composed of one or more characters from the following set:
! % & * + -, / < = > ? @ \ ~ |
Previous | Table of Contents | Next |