Previous Page Next Page

Chapter 3
OBJECTS AND MESSAGES

Now that you have toured the Smalltalk/V environment, you are ready to learn about the Smalltalk language itself. This chapter focuses on the concepts of objects and messages, the basis of the Smalltalk language. You'll also be introduced to global and temporary variables.

Throughout the tutorials you will be asked to evaluate sample pieces of code. As described in the previous chapter, you can find these examples stored in a disk file. Simply use the Open... item in the File menu to access these files. The examples for this chapter are stored in the file chapter.3.

Even if you are an experienced Smalltalk programmer, use these examples. They will help you to understand the Smalltalk/V environment as well as introduce you to some advanced Smalltalk applications. Of course, if you are new to Smalltalk, these examples will be even more valuable.

Simple Objects

Objects are the basic building block of the Smalltalk language. They are analogous to pieces of data in other languages. For example,

'this is a string'

is a Smalltalk object, a string of characters. It's very much like a string in any other language. Here are some other simple Smalltalk objects that have counterparts in most languages:

1234   "an integer"
$A   "the single character A"
#( 1 2 3 )         "an array of three integer objects"

Look at the last example, the array. It's an object which itself contains other objects. Let's look at some more examples:

#( 'array' 'of' 'four' 'strings' )
#( 'array' 'of' 5 'strings' 'and' 2 'integers' )

As you can see from the last example, all of the objects contained inside of an object do not have to be of the same type or size. Part of the power of Smalltalk comes from this capability. Consider this more complex object:

#( 1 ( 'two' 'three' ) 4 )

This is an object (an array) with three objects inside of it. The second object in the array is another array of two strings.

Simple Message

Of course, an object can do nothing by itself. In Smalltalk, you send messages to objects to make things happen. Messages are similar to function calls in other languages. For example, look at this Smalltalk expression, composed of a single message:

20 factorial

This sends the message factorial to the object 20. To evaluate this expression, either find it in the tutorial file chapter.3 or type it into a pane and select it. Then use the Show It item in the Smalltalk menu to compile and evaluate the highlighted text. The result should be a very large integer:

2432902008176640000

Let's try another simple message. When you select and evaluate the following expression, the result should be the integer 15, the size of the string:

'now is the time' size

A message is composed of three parts: a receiver object, a message selector, and zero or more arguments. In the above example, the string is the receiver object, the message selector is size, and there are no arguments. Or consider:

#( 1 3 5 7 ) at: 2

In this example, the array is the receiver, at: is the message selector, and the 2 is the argument.

A message always returns a single object as its result, just like functions in most other languages. Similarly, the message selector is like the function name, and the receiver object is like the first function parameter. The above example asks for the second element of the array; the result is the integer 3.

Now try evaluating this example:

'20' factorial

A walkback window appears. Since 20 is enclosed in quotes, it is a string, to which factorial makes no sense. As this example illustrates, objects always know the messages that are appropriate for them. The Encyclopedia of Classes lists all of the different kinds of objects provided by Smalltalk/V, and the messages to which they respond. To get rid of the walkback, select Close in the System menu of the walkback window.

Unary Messages

Messages with no arguments are called unary messages. Try evaluating these unary messages:

#( 'array' 'of' 'strings' ) size
'now is the time' asUpperCase
'hello there' reversed
#( 4 'five' 6 7 ) reversed
$A asciiValue
65 asCharacter

Keyword Messages

Messages with one or more arguments are called keyword messages. Try evaluating these keyword messages:

'now is the time' at: 6
'Hello' includes: $e
'hello' at: 1 put: $H
'The quick brown' copyFrom: 4 to: 9

In the last two examples, the message selectors at:put: and copyFrom:to: are divided up by the arguments. Each argument, then, is preceded by a colon. In these examples, at:put: and copyFrom:to: work with strings, but these same messages work for arrays as well:

#(9 8 7 6 5 ) at: 3
#(1 ( 2 3 ) 4 5 ) includes: #(2 3)
#(1 0 4 5) at: 2 put: #(2 3)
#(9 8 7 6 5 ) copyFrom: 1 to: 2

From these examples, you may have noticed another important point: different kinds of objects can respond to the same message in different ways. These arrays respond differently to the at:put: and copyFrom:to: message selectors than the strings in the previous examples.

Arithmetic Messages

Smalltalk arithmetic looks the same as in most other languages. For example:

3 + 4

But, like other Smalltalk expressions, this is a message. The integer 3 is the receiver, + is the message selector, the integer 4 is the argument, and the integer 7 is the result.

Here are some more common arithmetic messages you can evaluate:

5 * 7   "multiplication"
5 // 2   "integer division (truncation)"
4 \\ 3   "integer remainder"
2 / 6            "rational division"

The last expression illustrates rational arithmetic, or the arithmetic of fractions. In Smalltalk, rational arithmetic is exact; there is no rounding or truncation. This is because Smalltalk represents the result in a fraction object as a numerator and a denominator (reduced to its simplest form), rather than computing an approximate real number.

Arithmetic expressions in Smalltalk also differ from most other languages in their order of evaluation. Smalltalk evaluates an arithmetic expression strictly from left to right, with no precedence among operators. For example, evaluate this expression:

3 + 4 * 2

The result is 14, not 11. You can, however, use parentheses to control evaluation order, as in this example:

3 + ( 4 * 2 )

You can perform floating point arithmetic as well:

1.5 + 6.3e2

You do not need a math coprocessor to take advantage of the floating point capabilities of Smalltalk/V. However, if your computer is equipped with a 80287, 80387 or similar compatible math chip, Smalltalk/V will take advantage of it.

Binary Messages

Arithmetic messages are examples of binary messages, messages with one argument and one or two special characters (other than digits and letters) as the selector. Binary messages are always evaluated strictly from left to right, unless you have used parentheses. For example, evaluate these non-arithmetic messages:

'hello', 'there'
#(1 2 3), #(4 5 6)

In these examples, the special character is the comma. It concatenates the argument with the receiver object.

Messages Inside of Messages

As we stated before, messages are like functions in that they return an object. Anywhere an object appears in an expression, you can use a message which returns a similar kind of object. For example, evaluate each of the following:

'hello' size + 4
'now' size + #( 1 2 3 4 ) size
#( 1 12 24 36) includes: 4 factorial

The last expression above is really two messages. 4 factorial is a unary message, and is computed first. The result then becomes the argument for the includes: message. Now evaluate this more complex expression:

4 factorial between: 3 + 4 and: 'hello' size * 7

This expression is composed of five messages. The five message selectors are factorial, size, +, *, and between:and:. As you can see, unary messages are always evaluated before binary messages, which in turn are evaluated before keyword messages. As usual, you can override this precedence by using parentheses:

'hello' at: (#( 5 3 1 ) at: 2 )

This expression is composed of two at: messages: one to an array, and one to a string. To see what happens when there are no parentheses, try:

'hello' at: #( 5 3 1 ) at: 2

This expression is a single message with two arguments. The message selector becomes at:at:, clearly not what we had in mind.

Expression Series

You can't do much with just a single expression. Here's a series of expressions, which you can evaluate as a single unit. Select the entire series before selecting Do It in the Smalltalk menu:

Window turtleWindow: 'Turtle Graphics'.
Turtle foreColor: clrBlack.
Turtle home.
Turtle go: 100.
Turtle turn: 120.
Turtle go: 100.
Turtle turn: 120.
Turtle go: 100.
Turtle turn: 120

Each message in the series is separated from the next by a period. We put each message on a separate line purely for appearance. The first line opens a window for drawing and creates the object Turtle, a pen. The receiver of all the messages in the following lines is the object Turtle. To get a different picture, close the Turtle Graphics window and change the word clrBlack to clrDarkGray in the expression series and evaluate the series again.

Cascaded Messages

A cascaded message is a shorthand way of writing a series of messages that are sent to the same receiver. For example, the following expression draws the same figure as the previous example (only with a thicker line and in a different color):

Window turtleWindow: 'Turtle Graphics'.
Turtle
defaultNib: 2;
foreColor: clrDarkGray;
home;
go: 100;
turn: 120;
go: 100;
turn: 120;
go: 100;
turn: 120

The Turtle receiver is written only once, and each message (except for the last) is terminated with a semicolon instead of a period. The indentation, again, is optional; it simply makes the code easier to read.

Simple Loops

We can simplify the above example by using a message that loops a specified number of times:

Window turtleWindow:'Turtle Graphics'.
Turtle
black;
home.
3 timesRepeat: [ Turtle go: 100; turn: 120 ]

In this example, the argument to the timesRepeat: message is a block of code. Blocks of code are written as a series of messages enclosed in square brackets, [like this]. We'd normally write the above example as:

Window turtleWindow: 'Turtle Graphics'.
Turtle
black;
home.
3 timesRepeat: [
Turtle
go: 100;
   turn: 120]

This makes the cascaded message inside the block easier to see. Close the Turtle Graphics window before continuing.

Objects and Messages Are Safe

The previous series of expressions illustrates another point about objects and messages. Objects have a state; they can remember things. Messages change an object's state. The Turtle object remembers its position, heading, and color. The messages black, white, and foreColor: change its color, the messages go: and home change its position, and the message turn: changes its heading. Let's look at another expression that emphasizes this point:

'hello' at: 1 put: 23

When you evaluate this expression, a walkback error window pops up because 23 is not a character. Since you can only change the state of the string by sending messages, the string can check the validity of the arguments. This makes Smalltalk a very safe language.

Temporary Variables

Temporary variables are so called because Smalltalk discards them as soon as you are done using them. Temporary variables are declared by enclosing them in vertical bars in the first line of an expression series. Temporary variable names must start with a lower case letter, while the rest of the name can be any combination of upper and lower case letters and digits. For example, look at this short program that uses three temporary variables and a loop to compute an array of several factorials:

| temp index factorials |
factorials := #(3 4 5 6).
index := 1.
factorials size timesRepeat: [
temp:= factorials at: index.
factorials at:  index put:  temp factorial.
index:= index + 1].
^factorials

The first line declares three temporary variables: temp, index, and factorials. A temporary variable can hold any type of object. To give it a value, you use an assignment expression.

Assignment Expressions

The above example uses four assignment expressions:

factorials := #(3 4 5 6).
index := 1.
temp:= factorials at: index.
index:= index + 1.

The first two assign objects to the temporary variables, while the last two assign the results of messages. Since the result of a message is always a single object, they actually assign objects to the temporary variables.

Return Expressions

The last expression in the factorial example above is:

^factorials

The caret ^ indicates that this is the value to be returned as the result of the expression series. Such a statement beginning with a caret is called a return expression.

Global Variables

Smalltalk/V has many objects built in, many of which are contained in global variables. Unlike temporary variables, Smalltalk does not automatically dispose of global variables when you are finished using them, and their use is not confined to a single set of expressions. For example, Smalltalk/V provides (among others) these three global variables:

Display
Transcript
Disk

Display is an instance of class Screen and is an object which holds all the information about what you see on your monitor. Global variables always contain a single object - although an object can have instance variables which contain other objects. For example, select Display, and then use the Show It choice in the Smalltalk menu to see its current contents. The result is itself a single object.

Global variable names always begin with an upper case letter, with the remainder upper and lower case letters and digits. Type the following, select it, and Show It:

Sammy

When the global variable does not currently exist, you get a dialog box which allows you to choose whether or not you want to create it. If you do not create the global variable, Smalltalk/V assumes you made an error, and displays an error message. Click the No button to leave Sammy undefined. This keeps you from accidentally creating global variables when you misspell something. As with temporary variables, you use assignment statements to assign values to global variables:

Sammy:= 'Sammy Jones'

Evaluate with Show It and click the Yes button to define this new global variable.

Putting It All Together

To conclude this first tutorial, here's a graphics program that draws flowers composed of several polygons on the right side of your display.

"Draw a polygon flower"
| sides length |
Window turtleWindow: 'Turtle Graphics'.
sides := 5.
length:= 240 // sides.
Turtle
black;
home;
north.
sides timesRepeat: [
Turtle go: length.
sides - 1 timesRepeat: [
Turtle
turn: 360 // sides;
      go: length] ]

The first line is a comment. Comments are any string of characters enclosed in double quote marks ("comment"). Smalltalk/V ignores comments when it compiles the program; they simply add clarity to the code. Comments can appear anywhere in an expression series.

Evaluate the above example, and note the results. For a slightly different flower, change the number of sides. To make the polygons spread further apart, change:

Turtle go: length

to the following expression:

Turtle
up;
go: length // 2;
down;
go: length.

Close the Turtle Graphics window, then select and evaluate your modified method. The result will be similar to the following, depending on the number of sides you have set:

Figure 3.1
Polygon Flower

What You've Now Learned

At this point, you should be familiar with:

If you want to review any of these topics, simply refer back to the appropriate section in this chapter. Of course, Part 3 describes all of these topics in greater detail.

Here's one final point which you can think about as you proceed on to the following tutorials. As we mentioned, Turtle, which you have been using throughout this tutorial, is a global variable. You have been able to use this variable in a number of different situations without knowing anything about its internal contents. This is a unique feature of Smalltalk and object-oriented programming. You can use an object simply by knowing its external behavior, without knowing anything of its internal behavior. You'll see further examples of this throughout the following tutorials.

Now that you've learned the above topics, you can proceed on to the next tutorial: control structures.

Previous Page Next Page