[prev] [up] [next]

Playing with Objects and Classes

In the following chapters we use the Pen class, which simulates a pen drawing on a surface.
Making use of this class has two advantages: first, it is very simple and thus easy to understand, second and even more important, it gives a graphical feedback of what we do and is therefore pure fun!

Drawing with a Pen

Pens are objects that can draw onto a drawing surface, such as a view (window) on the screen.
Let us first create both, a view and a pen, and assign them to workspace variables. This way we can later refer to them by name in any workspace. In Smalltalk, variables have to be declared before use, to help the programmer in detecting misspellings. This rule also applies to immediate evaluations in a workspace.

Let us declare these two variables now. First, open a Workspace via the Launcher's menu or by evaluating:

   WorkspaceApplication open
and create a variable named "myPen" by selecting the "Add Workspace Variable" menu item:

enter "myPen" into the appearing name dialog.
Repeat this procedure for a "myView" workspace variable.

Alternatively, you can change the workspaces settings, to automatically declare all unknown variables as workspace variables. Be aware that this opens the door to a bunch of strange errors when a variable's name is misspelled. Go to the "Workspace"-"Settings" menu for this.

Next, we must ensure that the Pen-class is present; it will be used in the following examples. For this, evalute "Smalltalk loadPackage:'stx:goodies'" in the workpace.

Then, evaluate the following code (in this or any other workspace):

    | view |

    myView := View new.
    myView width: 200.
    myView height: 200.
    myView open.

    myPen := Pen in: myView.
This creates and opens up another view (referred to by the name "myView"). In addition, it also creates a pen-instance and makes the workspace variable "myPen" refer to it.

A pen's internal state consists (among others) of its current drawing position on the canvas, the drawing direction and an up/down state.
Pens understand a bunch of useful messages, among them are:

home
positions the pen at the center of the window and sets its drawing direction to "east" (i.e. left-to-right)

north
changes the pen's drawing direction to "north" (i.e. up)

turn: degrees
makes the pen turn clockwise the given number of degrees

down
places the pen onto its drawing canvas (i.e. followup moves will leave a drawing on the canvas)

up
lifts the pen from its drawing canvas (i.e. followup moves will NOT draw on the canvas)

go: distance
makes the pen move forward along its drawing direction the given number of pixels

fillColor: aColorObject
changes the pen's drawing color


Views understand hundreds of useful messages (there is a whole chapter on that in the documentation). For now, we only need to know a single message:
clear
clears the window

The clear message is useful to remove any of the pen's previous drawings.

To make the pen draw a triangle, evaluate:

    myPen home.

    myPen go: 50.
    myPen turn: 120.
    myPen go: 50.
    myPen turn: 120.
    myPen go: 50.
    myPen turn: 120.
You get colored triangles with:
    myView clear.
    myPen home.
    myPen fillColor: (Color red).

    myPen go: 50.
    myPen turn: 120.
    myPen go: 50.
    myPen turn: 120.
    myPen go: 50.
    myPen turn: 120.

    myPen fillColor: (Color black).
to make it draw a nice picture, try (and understand):
    myView clear.
    myPen home.
    18 timesRepeat: [
	myPen go: 50.
	myPen turn: 120.
	myPen go: 50.
	myPen turn: 120.
	myPen go: 50.
	myPen turn: 120.

	myPen turn:20.
    ]
(notice the use of a block here, and the extra turn after the triangle has been draw).

Another nice picture (which also shows a good use of blocks) is generated by:

    |rect|

    rect := [:side | 4 timesRepeat:[ myPen go:side; turn:90 ] ].

    myView clear.
    myPen home.

    36 timesRepeat: [
	rect value:60.
	myPen turn:10.
    ]

Looking into our Pen

Occasionally, you may want to look inside an object - either for education, to understand what information is held privately within an object, or to find a bug, when wrong values are computed or held by an object.

To inspect the internals of an object, we use a so called Inspector, which can be opened by sending the object to be inspect an "inspect"-message.
Try:

    myPen inspect.
You see (scroll down the left list if you don't) that the pen keeps information about its current position ("locationX" and "locationY") and its drawing direction ("direction"). For now, ignore the other values.

Clicking on such an instance variable. The inspector shows the variable's value in the right so called code- or value pane.

It is also possible to interactively send messages to the inspected object from within the inspector. By entering the message expression into the code pane, and evaluating it (using "doIt") just like in a workspace.
Within the inspector, the inspected object is referred to by the pseudo-name "self"; Therefore, we cne send messages to the inspected object, even if no global- or workspace-variable refers to it.

As an excercise, let the pen draw something using self-messages from within an inspector.

Browsing Pen's Protocol

To see all messages that our pen understands, we can open a so called Browser on its class. A browser is a powerful tool, both to find your way through the system (browsing) and to create or modify classes.

Browsers operate on the class(es) as they are present in your running system - in contrast to other so called IDEs, which operate on a classes source code as contained in a file. Changes done in a browser take effect immediately and are immediately available. There is no need to leave the system, recompile or restart the program for such changes.

There are many ways to open up a browser:

- via the Launcher
by pressing the browser icon or selecting the "SystemBrowser" item in the classes menu.

- via a Workspace
by selecting an expression's text and then applying the "others"-"browseIt" popup-menu function

- via an Inspector
the menu also provides a "browseIt" popup-menu function to browse the selected private variable's class

- by evaluating an expression
the browser can also be opened programatically. Either by sending the "browse" message to a class or by sending an "open"-message to the browser-class itself.
You can also browse any objects class by simply sending it a "browse" message. Thus, to browse your pen's class, try:
    myPen browse.
Browsers are explained in detail in the "Programming Tools" section of this online document. For now, lets just find the Pen-class (use the "Find-Class" menu function in the browser's tool menu) and have a look at the Pen classes full protocol (select "*all*" in the protocol list, which is the second right list in the browser's upper area).

Excercises:

  1. Open a browser and find the Pen class.
  2. Can you find the implementations of the "go:" and "turn"-messages (in the Pen class) we used before ?
  3. With the help of the browser, have a look into the implementation and see what is going on there.
  4. Find and try (in a workspace) the spiral- and mandala-messages.

Adding a new Method to the Pen Class

Let's assume, that we often have to draw triangles with our pen, and become bored of writing the above piece of code again and again.
We want that pens understand a "triangle"-message so that we can write:
    myPen triangle.
and have the pen draw a triangle with sides of 50 pixel length.
In order to teach Pens this new trick, perform the following steps:
  1. Open a browser and navigate to the Pen class.
  2. make sure you have the "instance"-toggle selected (this is explained later).
  3. select the protocol "geometric designs" in the second-right-top-pane.
Now, your browser window should look like:

In the text-area at the bottm, replace the shown text with the code for the triangle-method, as:

    triangle
	self go: 50.
	self turn: 120.
	self go: 50.
	self turn: 120.
	self go: 50.
	self turn: 120.
The syntax is very simple: the first line defines the name of the new method (the selector), the rest are the statements to be evaluated, when a triangle message arrives at a pen. In this case, a bunch of messages is sent to the receiver-pen itself.

After you typed in (or copy-pasted) the text into the browser,

install that new method, by selecting the "accept" item of the text-areas popup-menu. You can type in any garbage you like, or even use the code pane as a scratchpad workspace. What counts is the contents when the "accept" is performed.

After the accept, the browser will update its views to reflect the change - especially, you will see colorization and other markings in the class- and method lists. These indicate changes done to the system, and are described in more detail in the System Browser's Documentation. Also notice, that the browser displays your code with some colorization. Finally, if you want the browser to pretty-print your code (that is: to indent it in a way to reflect the control flow), press the browser's "PrettyPrint" button. It is found in the upper tool-panel, beside the breakpoint traffic lights.

Now, try to send this new message to our old friend, "myPen" by evaluating (in a workspace):

    myPen triangle
Notice, that the pen class has been changed for a living object - we did not have to shutdown and restart any program. The existing pen instance learned the new message while being alive !
(Sorry to get so excited, but that is what makes an integrated development environment really "integrated")

Not only new code can be added this way. If you select any existing method, change it and finally accept it.

Excercises:

  1. Add another Pen-method named "triangle:" (with colon), which takes a single argument and draws a triangle with sides of that length.
  2. Once the above "triangle:" method works, change the older "triangle"-method (without colon) to invoke that new method. Such an action is called "refactoring" and is very common when working in Smalltalk. The goal is to have an algorithm or piece of code only once in the system. Avoiding such redundancy helps in the maintainability of a program.
  3. Add methods to draw squares and other geometric figures.
  4. Refactor your code by writing a central method (which takes the number of sides and side-length as arguments) and use that one as common-code helper for squares, triangles, rectangles etc.

Footnotes:
(*)
Integrated Environment:
In ancient times, this term meant that the programming environment was part of the executed program and vice versa. The first integrated programming environments were provided by Lisp and Smalltalk systems.
Nowadays, by the help of a herd of marketing jerks, the meaning of "IDE" degenerated to: "a set of tools that can be started by a common launcher or are bundled together into one single top window". Many of those IDEs still call external compilers, linkers or even debuggers.

From the Smalltalk perspective, these systems are not "integrated" at all, and would be called "sophisticated launchers" instead.


Continue in "Creating new Classes".


[stx-logo]
Copyright © 1996 Claus Gittinger Development & Consulting
Copyright © eXept Software AG

<cg at exept.de>

Doc $Revision: 1.17 $ $Date: 2021/03/13 18:24:49 $