Previous Table of Contents Next


4.3. Relationships Among Classes

An object encapsulates a set of variables and a set of methods that can operate on those variables. A class is a common specification of variables and methods that is shared in common by a set of related objects. Objects that share a common class definition are called instances of the class. A class definition is a template that describes the common characteristics shared by all instances of a class. Various Smalltalk implementations use differing means for specifying class definitions. For now, we will ignore these differences and use a fill-in-the-blank style of form to describe classes. The basic template for a class looks like this:

Class Name <identifier that is the class’s global name>
Superclass <global name of another class>
Instance Variables <list of identifiers>
Instance Methods
<source code of individual methods>

Following is the partial definition of a simple class whose instances might represent individual customers in a customer information system:

Class Name Customer
Superclass Object
Instance Variables name address customerNumber
Instance Methods
<source code of individual methods>

A class name is an identifier that is used to refer to a class within a Smalltalk program. By convention, class names should be capitalized. Class names have global scope within a Smalltalk program. They also must be unique. Class names can be used as read-only variables within Smalltalk expressions. A class name cannot be the target of an assignment operator. The value of such a variable is a class object. Messages to class objects are most commonly used to create new instances of the class. Consider these lines, for example:

  Customer new
         “a new instance of Customer”
  Array new: 5
         #(nil nil nil nil nil) “new 5-element, uninitialized   array”

The message selector new is most frequently used to create new instances of a class. The selector new: is used to create instances that can vary in size. The argument to new: specifies the size of the variable-sized part of the new object.

Although most objects are explicitly created by sending messages such as new, there are no messages for explicitly destroying objects. Smalltalk is a garbage-collected language. It is the responsibility of a Smalltalk implementation to automatically release any storage or other resources used by an object when the object is no longer accessible from any variable or statement of the program.

4.3.1. Instance Variables

The variables encapsulated by an object are called instance variables. A class definition specifies the number of instance variables and specifies a name for each variable. Instances of the class Customer, defined in the preceding example, have three instance variables: name, address, and customerNumber. The instance variables of an object are directly accessible only by that object’s methods. This is accomplished by limiting the scope of the instance variable names to those methods.

The instance variables of multiple instance of a class are separate and distinct. If two instances of Customer are created, then each instance has distinct instance variables corresponding to name, address, and customerNumber. When a method is selected for execution as the result of a message send, the instance variable names in the method are bound to the actual instance variables of the object that is the receiver of the message.

The default value of all instance variables of a newly created object is nil. Typically, a programmer will want to initialize the values of some or all of the instance variables to more useful values. This cannot be done by direct assignment because instance variables are encapsulated and cannot be directly accessed outside of the object’s methods. To initialize the instance variables, a method is needed. Consider these lines, for example:

  name:  initName address: initAddr customerNumber: initNumber
         “initialize the state of the receiver to the argument values”
         name := initName.
         address := initAddr.
         customerNumber := initNumber

This is a simple method definition. The first line of the method is called the message pattern. It specifies the selector of the method and declares names for the arguments to the method.

4.3.2. Method Definition

Within the body of a method, argument names can be used as read-only variables. The second line of the method is a comment. Conventionally, a comment is placed here to describe the purpose of the method. The rest of the method is the method body, which consists of a sequence of Smalltalk expressions that are executed when this method is evaluated by a message send. In this example, the body simply consists of a set of assignments of argument values to instance variables. When the method is evaluated, the argument names are bound to the actual arguments of the invoking message, and the instance variable names are bound to the actual instance variables of the receiver of the message.

Methods always return some value. The return value can be explicitly specified using a return statement. A return statement is a Smalltalk expression immediately preceded by a carat (^). The value of the expression becomes the returned value of the method. Here are examples of some return statements:

  ^42            “return the literal integer object, 42”
  ^name          “return the current value of an instance variable”
  ^Customer new  “return a new Customer object”

Many methods, such as the one above, are not written with a return statement. If a method does not end with an explicit return statement, the method implicitly returns the object that was the receiver of the message that activated the method. Within the body of a method, the identifier (self) is bound to the receiver of the message. Thus, the following method definition is exactly equivalent to that given previously:

  name: initName address: initAddr customerNumber: initNumber
        “initialize the state of the receiver to the argument values”
        name := initName.
        address := initAddr.
        customerNumber := initNumber.
        ^self


Previous Table of Contents Next