Smalltalk Language
Messages
Construct a message
A
message expression
is made up of a
message receiver
and a
message selector
. The receiver is the object from which a service is being requested. The message selector is the name of the receiver's method that provides the service, along with any necessary arguments.
There are three message forms:
unary message
A message sent to a receiver with no arguments:
1.0 sin
keyword message
A one or more argument message selector, each argument following a keyword:
'9942-Steering wheel' copyFrom: 1 to: 4
binary message
A single argument message using one or two special symbols as the message selector instead of a keyword:
2 + 3
Send a message to a class
Since a
class
is an
object
, you can name a class as the
receiver
of a message. Messages appropriate for sending to a class (class messages) are separate from those sent to an instance.
Class messages are most often used for creating an instance of the class, as in the following example.
Date today
Send a message to the result of another message
Since the result of a message is an
object
, it can be the
receiver
of another message. Parsing, as usual, is from left to right.
1.0 sin squared
which returns the square of the sine of 1.0.
For complex expressions, you may need to use parentheses to control the parsing order.
See also:
Control parsing order
Use the result of a message as an argument
Since the result of a message is an
object
, you can use it directly as an argument in a message. Unary messages are parsed first.
52 * Random new next.
For complex expressions, you may need to use parentheses to control the parsing order.
See also:
Control parsing order
Control parsing order
In a complex expression, messages are executed from left to right, starting with unary messages, then binary messages, then keyword messages. Use parenthesis to specify the parsing sequence.
Compare:
2 * 3 + 2 2 * (3 + 2)
Expressions inside parentheses are evaluated before those outside. Parentheses can be nested.
Send a sequence of messages
Smalltalk style favors short, simple messages. Rather than construct a complex expression, which can be difficult to understand, write a sequence of simpler expressions, each on a separate line, terminated by a period. Use temporary variables as necessary.
For example, instead the complex expression:
52 * Random new next.
consider using a sequence of messages:
| generator random | generator := Random new. random := generator next. 52 * random.
Send multiple messages to the same receiver (cascading)
When sending a series of messages to the same
receiver
, use a semicolon to separate the messages. You only name the receiver once, at the beginning of the series. End the series with a period.
| flavors | flavors := OrderedCollection new.

flavors add: 'Vanilla'; add: 'Chocolate'; add: 'Cookie Crumble'; add: 'Rocky Road'; add: 'Raspberry Swirl'.

^flavors
Using Variables
Variable types
VisualWorks has four types of variables, largely distinguished by their scope:
temporary variable
Accessable only within a single method or workspace `DoIt` .
instance variable
Referenceable by that object (instance) only. Inherited by all subclasses.
class instance variable
Created separately (not shared) for the defining class and each of its subclasses.
shared variable
Variables of a more general scope, which may be declared public or private relative to a
namespace
. Shared variables may be shared within a single class (class variables), all of its subclasses, and all of their instances; alternately, they may be shared by all objects within a single name space (name space variables). It is possible to
import
a shared variable in other name spaces.
Shared variables replace pool, global, and class variables.
Store a value in a variable
To assign a value (an
object
) to a variable, use the `:=` assignment operator:
| sine | sine := 1.0 sin.
Classes may define special assignment methods for its variables that provide special assignment features. Using the assignment operator directly will not take advantage of such features.
Provide access to a variable's value
While only an
object
can directly access its variables, it is often useful to give access to the value of an object's variables, such as instance variables holding the object's properties. This is done using accessing methods.
For example, a class `Ball` may define a instance variable `color` to answer the object's color, `Ball` may implement the method:
color ^color.
To allow setting its color, `Ball` may implement the method:
color: aColor color := aColor.
This naming scheme is standard for accessors in Smalltalk.
(Why would I) Use class instance variables?
A
class instance variable
is declared once, in a parent class. Each subclass then has its own copy of the variable and can assign to it independently.
Unlike a
shared variable
, which may be used by several classes, each class has its own class instance variables, and so must initialize them individually. The advantage of the class instance variable is that all subclasses can use the same name for the variable and still be able to assign to it independently.
(Why would I) Use pools or class variables?
With VisualWorks 5i, pools and class variables were superseded by shared variables.
See also:
(Why would I) Use shared variables?
(Why would I) Use shared variables?
Shared variables replace what were formerly class variables and pools. They have general scope within their name space, which may be a name space or a class, depending on where they're defined. Access to them from outside that scope is achieved by importing them.
Declaring Variables
Declare a temporary variable
A temporary variable must be declared at the beginning of the method or Workspace Do It in which it is used. To do so, place its name between vertical bars.
| variable |
By convention, a temporary variable's name begins with a lowercase letter.
| numberOfDays date | numberOfDays := 7. date := Date today addDays: numberOfDays.
Automatically declare variables
In practice, you can freely use new variable names and rely on the VisualWorks system to prompt you when it encounters each undeclared variable name. Indicate the variable's type is the displayed dialog, and the system creates the declaration for you.
Declare an instance variable
Instance variables are declared in the class definition. An instance variable's name should begin with a lowercase letter.
Open a browser and select the class.
If necessary, select the browser's Source code tool to display the class definition.
Add the desired instance variable name to the list of `instanceVariableNames:` and then Accept the new definition.
Declare a class instance variable
Class instance variables are declared in the class definition. A class instance variable's name must begin with an uppercase letter.
Open a browser and select the class.
If necessary, select the browser's Source code tool to display the class definition.
Add the desired instance variable name to the list of `classInstanceVariableNames:` and then Accept the new definition.
Declare a class variable
In VisualWorks 5i, class variables were superseded by shared variables.
See also:
(Why would I) Use shared variables?
Declare a shared variable
Declare a shared variable
Shared variables are defined within the scope of either a name space or a class. To create a shared variable:
Select a name space or class in the System Browser.
On the Class menu, select New->Shared Variable . A definition template appears in the browser's code view.
Complete and Accept the following template:
Smalltalk defineSharedVariable: #NameOfBinding private: false constant: false category: 'As yet unclassified' initializer: 'Array new: 5'
The template specifies a message send to the name space or class in which the shared variable name is to be resolved.
See also:
(Why would I) Use shared variables?
Declaring a shared variable as a constant
A shared variable is set to be either a constant or variable value by the argument to the `constant:` keyword in its definition. By default the argument is `false` . To make it constant, set the argument to `true` .
The value of a shared variable can be set during runtime. If the value is constant, it can only be reset in the variable's initialization.
See also:
Declare a shared variable
Initialize a shared variable
Initialize a shared variable
The `initializer:` keyword in a shared variable's definition accepts either a Smalltalk expression written as a string, or `nil` .
If a Smalltalk expression string is provided, it is evaluated and the result set as the initial value of the variable.
If the initializer is specified as `nil` , the initial value can be set in a class initialization method, as for class variables in earlier versions.
See also:
Declare a shared variable
Privacy for shared variables
The `private:` keyword in a shared variable's definition specifies whether it is exported to (available for import to) other classes or name spaces. The default value is `false` , making the variable public. To make it private, set this value to `true` .
See also:
Import a shared variable
Import a shared variable
Shared variables are imported into a name space or class scope by including them in the argument to the `imports:` keyword of the name space or class definition. They may be imported by either a general or an specific import.
See also:
Importing to a name space
Removing Variables
Remove a temporary variable and its references
Since a temporary variable can be referenced only in a single method or Workspace Do it , you need to scan only that method for references. For a long method, use the Find... command to find each occurrence of that variable in the code. Rewrite the code as needed to remove each reference.
After you have removed all references, delete the variable declaration.
Remove an instance variable and its references
In a browser, select the class in which the variable is declared.
On the Class menu, select Instance Variables->Remove... .
In the resulting menu of instance variables, select the variable that you intend to remove.
If any methods reference the variable, a Method browser will open. The variable will not be removed as long as there are methods that reference it.
The new Method browser displays all methods that reference the variable. Edit the methods to remove the references.
When all references have been removed, close the Method browser.
On the Class menu, select Instance Variables->Remove... .
The instance variable should now be removed.
Remove a class instance variable and its references
In a browser, select the class in which the variable is declared.
On the Class menu, select Class Instance Variables->Remove... .
In the resulting menu of class instance variables, select the variable that you intend to remove.
If any methods reference the variable, a Method browser will open. The variable will not be removed as long as there are methods that reference it.
The new Method browser displays all methods that reference the variable. Edit the methods to remove the references.
When all references have been removed, close the Method browser.
On the Class menu, select Class Instance Variables->Remove... .
The class instance variable should now be removed.
Remove a shared variable and its references
In a browser, select the class in which the variable is declared and select the Shared Variables tab.
On the Method menu, select Safe Remove .
If any methods reference the variable, a Method browser will open. The variable will not be removed as long as there are methods that reference it.
The new Method browser displays all methods that reference the variable. Edit the methods to remove the references.
When all references have been removed, close the Method browser.
On the Method menu, select Safe Remove .
The shared instance variable should now be removed.
Remove undeclared variables
When a variable is referenced without being declared, it is entered in a system dictionary named `Undeclared` . If it is later declared, the entry in `Undeclared` remains and should be removed before you deploy your application.
To remove undeclared variables, open an inspector on `Undeclared` (evaluate `Undeclared` using the Inspect command). Use the dictionary inspector to check for references to each entry and to remove each entry that has no entries.
Methods
Browse a method
To browse only the currently selected method (with a Method Browser), use <Operate> in the methods view and select Spawn .
Create an instance method
New methods are created by editing the method definition template that appears in the code view of any browser.
In a System Browser, click on the Instance tab.
Select the class.
Select the desired protocol or add one using New... .
Fill in the method template and then select Accept on the <Operate> menu in the code tool. The new method is compiled and added to the currently selected protocol.
Create a private method
Smalltalk has no private methods. If you want to let others know that a message should only be sent by instances of a class and not by other classes, you typically would put the method in a protocol with "`private` " in the name. This merely acts as a suggestion though.
Create a class method
New methods are created by editing the method definition template that appears in the code view of any browser.
In a System Browser, click on the Class tab.
Select the class.
Select the desired protocol or add one using New... .
Fill in the method template and then select Accept on the <Operate> menu in the code view. The new method is compiled and added to the currently selected protocol.
Name a binary method
A binary method consist of one or two of the following special characters: plus sign (`+` ), dash(`-` ), asterisk(`*` ), forward slash(`/` ), back slash(`\` ), ampersand(`&` ), vertical bar(`|` ), greater than sign(`>` ), less than sign(`<` ), equal sign(`=` ), tilde(`~` ), at sign(`@` ), percent sign(`%` ), question mark(`?` ), exclamation mark(`!` ). If it contains a dash, then it can only contain it as the first character.
Find a method by name
Select a class, then use <Operate> in the browser's protocols view and select Find Method... . A dialog box will prompt you with a list of all methods in the currently selected class.
Find references to a method
To browse all other methods that call the method you are viewing, use the Senders commands on the <Operate> menu in the methods view.
To search for all methods that contain explicit references to the method you are browsing, choose Senders , ignoring the fold-out menu options. Note that all methods containing either explicit message sends or symbols that match the selector you are searching for will be added to the list of senders (this helps to identify code that uses `perform:` ).
Use the fold-out menu to browse Senders of messages sent in the current method. To search for all methods sending those messages, pick one of the items lower on the list, or pick more items... to see a complete list.
To search more narrowly for senders within the same branch of the class hierarchy you are browsing, use Local senders instead of Senders .
Find implementors of a method
To browse all other methods with the same name as the one you are viewing, use the Implementors commands on the <Operate> menu in the methods view. To search for all methods with the same name as the one you are browsing, use Implementors , ignoring the fold-out menu options.
Use the fold-out menu to browse Implementors of messages sent in the current method. To search for all other implementors of the messages sent, pick one of the items lower on the list, or pick More implementors... to see a complete list.
To search more narrowly for implementors within the same branch of the class hierarchy you are browsing, use Local implementors instead of Implementors .
Remove a method
In a System Browser, select the method.
Select the Remove... command on the <Operate> menu in the methods view.
Locate missing source code for a method
Source code for methods is stored in a single
sources file
associated with your VisualWorks image. If you see code in the browser with a comment explaining that it is decompiled code, the system source or changes file is not correctly identified with your image . To correctly identify the sources file, open the Settings Tool (select System->Settings in the Launcher window) and edit the Source Files page, making sure the " .sou " file name agrees with the image name.
See also:
Set source and changes files
Returning Values
Return a value from a method
Every method returns a single object,by default the object that received the message. When another object should be returned, such as a more interesting value, you can specify that object by using a caret symbol ( `^` ).
accountID ^accountID
Return from a block
When a return character is enclosed within a block, it forces a return from the entire method. That is, it does not act as a return from the block back to the containing method.
Return the result of a message
A return character that is followed by a message returns the result of that message.
displayString ^accountID printString, '--', name
This approach often circumvents the need to create a temporary variable for the message result.
Return a value on condition
Frequently, a method performs a test and returns one value if the test result is true and a second value if the test result is false. Relying on the fact that a return character that is followed by a message returns the result of the message, you can use a single return caret to serve both forks of the branch, rather than placing a caret inside each block.
accountPrefix "Answer the first four characters of the accountID, or an empty string if the accountID is empty."

| id | id := self accountID.

^id isEmpty ifTrue: [String new] ifFalse: [id copyFrom: 1 to: 4].
Accessing Objects
Access a distinguished instance
When a class is intended to provide just one instance of itself, that instance is referred to as a
distinguished instance
. Typically, it is stored in a shared variable and accessed using an
accessing method
named `default` .
Send a `default` message or other accessing message to the class. (Use the Inspect command to open an Inspector on the instance, so you can see how the instance variables differ from those of a `new` instance.)
SourceFileManager default.
Initializing Objects
Create an 'initialize' method
Write an `initialize` method to set initial instance variable values for a new object instance. This is often necessary to prevent errors that result when client methods send messages to the uninitialized instance variables.
ApplicationModel
and its subclasses invoke `initialize` by default. Other classes must invoke `initialize` method explicitly in their instance-creation methods.
Create an instance method named `initialize` in an `initialize-release` protocol.
initialize accountID := 0. name := String new. address := String new. phoneNumber := String new.
Create a class method named `new` in an `instance creation` protocol which invokes `initialize` .
new ^super new initialize
Online example: Customer1Example
Use a parent class's initialization
When implementing an `initialize` method, be aware that a parent class may also have an `initialize` method. If so, invoke the parent class's `initialize` as a first step in the subclass's `initialize` .
initialize super initialize. yearsOfPatronage := 3.
Online example: PreferredCustomerExample
Protocols
Browse a protocol
To browse only the currently selected protocol (with a Protocol Browser), use <Operate> in the protocols view and select Spawn .
Create a protocol
Placing related methods in a message category, also known as a
protocol
, helps to document your code and makes it easier to find with a System Browser. Your choice of protocol name has no effect on your code's operation.
In a System Browser, select the class.
Select the New... command in the protocols view.
In the resulting dialog, supply the name of the protocol (no harm is done if it already exists). Type a blank space to cancel the operation.
The new protocol is inserted in the list above the protocol that was previously selected. To insert it at the bottom of the list, make sure no protocol is selected when you begin step 1.
Remove a protocol
Removing a protocol that has methods in it removes the methods also.
In a System Browser, select the protocol.
Select the Remove... command in the protocols view.
If the protocol contains methods, you will be asked to confirm the removal.
Rename a protocol
In a System Browser, select the protocol.
Select the Rename... command in the protocols view.
In the resulting dialog, supply the new name. Type a blank space to cancel the operation.
Move a method to a different protocol
In a System Browser, select the method.
Select the Move->to Protocol... command in the methods view.
In the resulting dialog, supply the name of the destination protocol. If the protocol does not exist, it will be created. Type a blank space to cancel the operation.
Copy a method to a different class
In a System Browser, select the method.
Select the Move->to Protocol... command in the methods view.
In the resulting dialog, enter the name of the destination class, a greater-than symbol ( > ), and the name of the destination protocol (i.e., `MyClass>initialization` ). To copy the method to the class side rather than the instance side, insert " class " after the class name.
Classes
Browse a class
To browse only the selected class (with a Class Browser), use <Operate> in the browser's classes view and select Spawn .
To browse only the classes in the same branch of the class hierarchy (with a Class Hierarchy Browser), use <Operate> in the classes view and select Spawn Hierarchy .
See also:
Set options for browsing
View a class' behavior
Use the Instance and Class tab controls in the System Browser to toggle between showing class and instance behavior.
View a class hierarchy
With one class is selected in the System Browser, select the Hierarchy tab in the navigator (it may be necessary to deselect a protocol in order to see the hierarchy.)
To open a separate Hierarchy Browser, select Class->Spawn Hierarchy .
See also:
Set options for browsing
View references to a class
Select a class, then select References on the Class menu. A new browser will open showing a list of all methods in the system that directly reference the selected class.
Find a class by name
Enter the class name into the input field in the upper-right corner of the Browser. You may enter the beginning of a class name, or use the wildcard character " * " to narrow your search. Enter <Return> to perform the find.
Save a class
To save the complete definition of a class as a disk file, select the class and use File Out As... on the <Operate> menu in the classes view. A dialog box prompts you for the name of the file. By default, the class is saved in a file called NameOfClass.st .
To save a single protocol or a single method, use File Out As... in the protocols or methods view.
Note: Parcels are now the preferred mechanism for storing classes in files.
Creating a Class
Choose a class type
When creating a new class, you must choose from one of the three available types:
Fixed Size
Instances will be fixed in size, with named instance variables only.
Variable
Instances are variable-sized, with indexed instance variables which contain objects.
Bytes
Instances are variable-sized, with indexed instance variables contain one byte each.
In the class creation template, you can specify either a `Fixed` , `Variable` , or `Byte` type class using the `indexedType:` keyword with the argument `#none` , `#objects` , or `#bytes` , respectively.
See also:
Create a new subclass
Create a collection class that holds pointers to its elements
Create a collection class that holds byte-sized elements
Create a new subclass
A class name can contain letters, numbers and underscores, but cannot begin with a number. Class names must begin with a capital letter.
Select the name space and class category in a System Browser where you would like to place the new class.
On the Class menu, select New->Class .
Edit the class-creation template, entering at least the name space (`Examples` ) and the name of the new subclass.
Smalltalk.`Examples` defineClass: #Customer1Example
superclass: #{Core.Object}
indexedType: #none
private: false
instanceVariableNames: 'accountID name address phoneNumber'
classInstanceVariableNames: ''
imports: ''
category: 'Examples-Help'
To add the class to the system, select the Accept command in the code view.
See also:
Choose a class type
Create a collection class that holds pointers to its elements
Create a collection class that holds byte-sized elements
Create a collection class that holds pointers to its elements
Use the System Browser to create a class that holds a collection of indexable variables, each of which is a pointer to an object.
Select the name space and class category where you would like to place the new class.
On the Class menu, select New->Indexed Class .
Edit the class-creation template, entering at least the name space (`Examples` ) and the name of the new subclass.
Smalltalk.Examples defineClass: #ExampleVariableClass
superclass: #{Core.Object}
indexedType: #objects
private: false
instanceVariableNames: ''
classInstanceVariableNames: ''
imports: ''
category: 'Examples-Help'
To add the class to the system, select the Accept command in the code view.
See also:
Choose a class type
Create a collection class that holds byte-sized elements
Create a collection class that holds byte-sized elements
Use the System Browser to create a class that holds a collection of indexable variables, each of which is a pointer to an object.
Using the System Browser, select the name space and class category where you would like to place the new class.
On the Class menu, select New->Byte Indexed .
Edit the class-creation template, entering at least the name space (`Examples` ) and the name of the new subclass.
Smalltalk.Examples defineClass: #ExampleVariableClass
superclass: #{Core.Object}
indexedType: #bytes
private: false
instanceVariableNames: ''
classInstanceVariableNames: ''
imports: ''
category: 'Examples-Help'
To add the class to the system, select the Accept command in the code view.
See also:
Choose a class type
Create a collection class that holds pointers to its elements
Create a subclass of ApplicationModel or SimpleDialog
For the convenience of interface programmers, the Install command in a Canvas provides a convenient dialog box for creating new subclasses of `ApplicationModel` and `SimpleDialog` .
Choose `SimpleDialog` as the parent when instances of the new class will be used primarily to run one or more dialog windows.
Choose `ApplicationModel` as the parent when instances of the new class will be used to run regular windows as well.
Name Spaces
Create a name space
Use the System Browser to create a
namespace
(choose Browse->System in the
Launcher
window):
Select the parent namespace (typically, this should be `Smalltalk` ) in the browser's class view, and choose Class->New->Name Space . A namespace definition template appears.
Edit the template, entering at least the name space (`Examples` ). Change the receiver name space if necessary, although normally you should only define namespaces under `Smalltalk.` Also set any imports and a category name for the name space. For example:
Smalltalk defineNameSpace: #Examples
private: false
imports: '
private Smalltalk.*
'
category: #'Examples-Unclassified'
Accept
your changes to create the new name space.
See also:
Naming name spaces
Create a private name space
Importing to a name space
Naming name spaces
Create new parent name spaces under `Smalltalk` . In general, the `Root` namespace should not be used as a parent.
For example:
Smalltalk defineNameSpace: #WidgetSystems
private: false
imports: '
private Smalltalk.*
'
category: #'WidgetSystems-Unclassified'
Namespace names and hierarchies should be selected to help avoid collisions. We recommend using a long form of your company name, since it is less likely to be used by someone else. Thus, in the example, `WidgetSystems` is less likely to cause a clash than would `WS` .
Cincom provides a Wiki server on which companies can reserve top-level name space names. For details, see:
http://www.cincomsmalltalk.com:8080/CincomSmalltalkWiki/VW+NameSpace+Reservations
See also:
Create a name space
Create a private name space
Name spaces, classes, and shared variables are defined as either public or private. By default, new name spaces are public and thus exported and available for import by another name space or class.
To create a private name space, use the System Browser:
Select the parent namespace in the browser's class view, and choose Class->New->Name Space . A namespace definition template appears.
Edit the template, setting the `private:` argument to `true` . Also enter the new name (e.g., `Examples` ), any imports and a category name for the name space. For example:
Smalltalk defineNameSpace: #Examples
private: true
imports: '
OtherNameSpace.*
private Smalltalk.*
'
category: #'Examples-Unclassified'
Accept
your changes to create the new, private name space.
See also:
Importing to a name space
Importing to a name space
Name space and class definitions can specify the names of bindings to import. A binding can be imported only if it is defined as public, or imported as public into another imported name space.
To create a name space that imports other bindings, use the System Browser:
Select the parent namespace in the browser's class view, and choose Class->New->Name Space . A namespace definition template appears.
Edit the template, entering the name (e.g., `GraphicsExamples` ) and category name for the new name space. Specify all imports using a single string argument to the `imports:` keyword. For example:
Smalltalk defineNameSpace: #GraphicsExamples
private: false
imports: '
Graphics.SymbolicPaintConstants.ButtonHilite
private Smalltalk.*
'
category: #'Examples-Graphics'
Accept
your changes to create the new name space.
See also:
Choosing appropriate name space imports
Choosing appropriate name space imports
When a name space imports bindings, the import declaration may be either specific or general . For example, in this definition:
Smalltalk defineNameSpace: #GraphicsExamples
private: false
imports: '
Graphics.SymbolicPaintConstants.ButtonHilite
private Smalltalk.*
'
category: #'Examples-Graphics'
The first, specific import , specifies a single public binding name:
Graphics.SymbolicPaintConstants.ButtonHilite
The second, general import , specifies all public bindings in a class or name space, by appending an `*` (asterisk) as the final name in a binding reference:
Smalltalk.*
As a rule, a general import should make its imports `private` , as in:
private Smalltalk.*
When a name space makes an import `private` , another name space that imports it is prevented from importing that private binding, at least via this name space.
See also:
Importing to a name space
Imports into Smalltalk
Imports into Smalltalk
As a provisional measure, to ensure that pre-5i code works in a version 5i (or later) image, the `Smalltalk` name space imports all bindings from all of the child name spaces defined in the base, and all of the child name spaces import all of the bindings in `Smalltalk` .
So, in the definition of the `Smalltalk` name space, you see `Core.*` as an import, and in the definition of `Core` you see `Smalltalk.*` imported. There is also a shared variable `Smalltalk` defined in the `Smalltalk` name space to allow it to refer to itself.
This circularity can be confusing, and is a temporary measure. While your name spaces can import`private Smalltalk.*` to gain the access to system classes, you should be careful to import only those system name spaces that you need.
See also:
Referencing bindings
Remove a name space
Removing a
namespace
that has classes in it removes the classes also.
In a System Browser, select the name space.
Select the Remove... command from the Class menu.
If the name space contains classes, you will be asked to confirm the removal.
Rename a name space
When you rename a
namespace
, the new name appears automatically in the definition of each class in that category.
In a System Browser, select the name space.
Select the Rename... command from the Class menu.
In the resulting dialog, supply the new name. Type a blank space to cancel the operation.
Class Categories
Browse a class category
To browse only the classes in the selected
category
, use <Operate> in the categories view and select Spawn .
Create a class category
Use a class
category
to organize your classes into groups. Many tools allow you to work on categories as well as on individual classes. The browser's navigator is set to view categories when you click on the Category tab.
In a System Browser, select the New... command in the class-category view.
In the resulting dialog, supply the name of the category (no harm is done if it already exists).
The new class category is inserted in the list above the category that was previously selected. To insert it at the bottom of the list, make sure no category is selected when you begin step 1.
Remove a class category
Removing a class
category
that has classes in it removes the classes also.
In a System Browser, select the category.
Select the Remove... command in the class-category view.
If the category contains classes, you will be asked to confirm the removal.
Rename a class category
When you rename a class
category
, the new name appears automatically in the definition of each class in that category.
In a System Browser, select the category.
Select the Rename... command in the class-category view.
In the resulting dialog, supply the new name. Type a blank space to cancel the operation.
Move a class to a different category
In a System Browser, select the class.
Select the Move->to Category... command in the class view.
In the resulting dialog, supply the name of the destination category. If the category does not exist, it will be created.
Creating Instances
Create an instance with 'new'
All classes inherit a basic `new` method from the `Object` class. This method creates a raw instance whose instance variables each have the value `nil` .
SourceFileManager new.
Abstract classes, such as `Boolean` , typically override `new` in which they announce an error such as `"This class is not intended to be instantiated."`
Classes frequently override `new` in order to initialize instance variables.
Use a class-specific creation message
Classes frequently define specific creation messages. These frequently take arguments that are used to initialize the instance variables of the new instance.
Date newDay:10 month:#June year:1995
Such
parameterized
creation messages are often convenience methods. The same effect usually can be achieved by first creating a `new` instance and then sending the parameters via
accessing
messages.
Bindings
What is a binding?
Bindings are a new construct in VisualWorks 5i. They are used to implement shared objects such as classes, namespaces, and shared variables. Their value is often constant, and they can be referenced, imported, and queried (as instances of class `BindingReference` ).
Referencing bindings
References to bindings (namespaces, classes, and shared variables) use a dotted notation that describes the path through the name space hierarchy to the desired binding. Binding references begin with the `Root` name space, continuing through the hierarchy to the target binding. For example, the full reference to the `ButtonHilite` constant is:
Root.Smalltalk.SymbolicPaintConstants.ButtonHilite
.
References to bindings in a name space under `Smalltalk` can omit the initial segment `Root.Smalltalk` , which is assumed. So, the above reference to `ButtonHilite` can be shortened to:
SymbolicPaintConstants.ButtonHilite
The dotted names can be used to refer to a binding that has not been imported.
Usually you will refer to a binding that has been imported. The notation `#{MyBinding}` allows referring to the binding `MyBinding` without specifying its name space path. So, if a name space imports the `SymbolicPaintConstants.ButtonHilite` , references to it can be simply:
#{ButtonHilite}
Branching and Looping
Create a conditional branch
Branching, or conditional processing, is accomplished by sending a variant of the `ifTrue:` message to the result of a true/false test. The conditional statements are enclosed in a block.
The full set of variants is:
ifTrue:
ifFalse:
ifTrue: ifFalse:
ifFalse:ifTrue:
Loop a fixed number of times (timesRepeat:)
Send a message to the Transcript 10 times.
10 timesRepeat: [Transcript show: 'Testing!'; cr.]
Loop with an index argument (to:do:)
Repeat a block using each number in the interval from 65 to 122. This block includes a
block argument
(`:asciiNbr` ), which is specified by an identifier preceded by a colon and separated from the block's expressions by a vertical bar. In each loop, a successive number in the interval is passed into the block and used where the block argument appears.
65 to: 122 do: [ :asciiNbr | Transcript show: asciiNbr asCharacter printString]
Loop with an index and steps (to:by:do:)
Repeat a block using each number in the interval from 10 to 65, counting by 5.
10 to: 65 by: 5 do: [ :marker | Transcript show: marker printString; show: '---' ].
Loop until a block exits (repeat)
Send the `repeat` message to the block to be repeated until the block returns true.
| counter | counter := 0.

[counter := counter + 1. counter > 10 ifTrue: [^true] ] repeat .
Loop on a true or false condition (whileTrue: and whileFalse:)
Send either a `whileTrue:` or `whileFalse:` message to a block that returns a boolean value, with a 0-argument block describing the action to perform on each loop.
| endTime | endTime := Time now addTime: (Time fromSeconds: 3).

[Time now <= endTime] whileTrue: [ Transcript show: Time now printString; cr].
Boolean Conditionals
Boolean operators
When two or more conditions need to be tested, use the logical and and or messages to combine the tests in a series. These messages come in two forms:
&
and `|` (vertical bar)
and:
and `or:` (the argument is a block containing the second test)
Use the second pair of messages when the second test depends on the result of the first test. In a common situation involving such a dependency, the first test checks the data type of a variable and the second test sends a message that is appropriate only for the desired data type.
Using the second form, involving block arguments, is also appropriate when the second test is costly, because the second test is executed only when needed.
Answer true when both tests are met (logical "and")
Send an`&` or `and:` message to an expression that returns a boolean value.
The `&` message takes any expression that also evaluates to a boolean value. Both expressions are always evaluated.
| response message | response := Dialog request: 'What is your password'.

(response size > 0) & (response size <= 8) ifTrue: [message := 'Thank you. Have a safe journey'] ifFalse: [message := 'Sorry, I cannot let you pass'].

Transcript show: message; cr.
The `and:` message takes a block that evaluates to a boolean value. The block is evaluated only if the first expression evaluates as true.
| response message | response := Dialog request: 'What is your password'.

((response size > 0) and: [response size <= 8]) ifTrue: [message := 'Thank you. Have a safe journey'] ifFalse: [message := 'Sorry, I cannot let you pass'].

Transcript show: message; cr.
Enumerating a Collection
Enumerate each element of a collection (do:)
Send a `do:` message to a collection, with a block describing the action to perform on each element.
| colors | colors := ColorValue constantNames.

colors do: [ :colorName | Transcript show: colorName printString; cr]
Detect the first element that meets a test (detect:)
Send a `detect:` message to a collection with a block describing the detection criterion.
| colors mColor | colors := ColorValue constantNames.

mColor := colors detect: [ :colorName | colorName first = $m]. Transcript show: mColor printString; cr.
Select all elements that meet a test (select:)
Send a `select:` message to a collection with a block describing the selection criterion.
| colors dColors | colors := ColorValue constantNames.

dColors := colors select: [ :colorName | colorName first = $d].

dColors do: [ :dColor | Transcript show: dColor printString; cr].
Select all elements that fail a test (reject:)
Send a `reject:` message to a collection with a block describing the rejection criterion.
| colors nonDColors | colors := ColorValue constantNames.

nonDColors := colors reject: [ :colorName | colorName first = $d].

nonDColors do: [ :nonDColor | Transcript show: nonDColor printString; cr].
Operate on a collection and collect the results (collect:)
Send a `collect:` message to a collection with a block describing the operation to perform on each element. The result is a collection, which generally should be assigned to a variable for future use.
| colors colorsAsStrings string | colors := ColorValue constantNames.

colorsAsStrings := colors collect: [ :colorName | string := colorName asString. string at: 1 put: (string first asUppercase). string].

colorsAsStrings do: [ :color | Transcript show: color; cr].
Errors During Compilation
Undeclared temporary variables
If you neglect to declare a temporary variable in a method definition, the system prompts you with a menu of variable types. If you select temp, the system adds the variable to the temporaries declaration.
Undeclared class and instance variables
If you neglect to declare a class or instance variable, the system prompts you with a menu of variable types. Select abort in the menu and declare the variables in the class definition before continuing.
To save your uncompiled method while you redefine the class, select Spawn in the code view. This opens a new browser on the uncompiled code.
Nothing more expected
This error usually occurs if you have omitted a period.