Chapter 5. Classes

Table of Contents
5.1. Inheritance
5.2. Object variables
5.3. Method overriding
5.4. Messaging super
5.5. Object allocation and initialization
5.6. Object destruction
5.7. Polymorphism
5.8. A class is not atomic
5.9. Multiple inheritance
5.10. Special classes
5.11. Collections

We now come to the most important subject of an object oriented programming language: how objects are constructed. We will use a simple Counter class as the example along which to explain the object basics. We know the following about Counter objects:

  1. each Counter object maintains information about its current value, and

  2. it responds to the nextValue message by returning the next value, thereby updating its current value.

This description only contains statements about the Counter objects, i.e. instances of the Counter class. Therefore the class definition can be empty, for now.

implementation class Counter end;

The Counter instances maintain a current value, and respond to the nextValue method. This is written thus:

implementation instance Counter
  int current_value;

  current_value += 1;
  = current_value;


The definition of the Counter instance starts with implementation instance Counter and ends with end;. Within this definition, between the first pair of braces an instance variable is defined. Instance variables form the state maintained by each instance of the current class: every Counter instance will have its own value of the current_value. This variable has the type int.

Following the instance variable declaration, the nextValue method is defined. This method has no arguments and returns an int. In the body of the method, the current_value instance variable of the current instance is incremented by 1, and the resulting value is returned. The current instance is the receiver of the message as a result of which the current method was invoked. Thus, in the following example

Counter count = ...;
int i = [count nextValue];

the count variable denotes a Counter instance; in the second line, the nextValue message is sent to it, and the nextValue method will be invoked, with the object we know as count as the receiver.

5.1. Inheritance

We now have a class definition, but no means yet to create instances. The language does not provide a mechanism to create instances; instead, this functionality is provided by the library. The TOM standard library contains a class State that provides the following method:

instance (id)

This class method returns a new instance of the receiving class. Thus, invoking

x = [State alloc];

will return a new instance of the State class. ``How does this help us to create Counter objects?'' you ask. By indicating that a Counter object is also a State object, which will cause the Counter objects to behave as State objects, and similar, that the Counter class behaves as the State class. This is called inheritance: every method defined by State is not only applicable to State, but also to Counter. To indicate that our Counter inherits from State, the class definition is changed to:

implementation class
Counter: State


Now any method or instance variable defined for the State class (or instance) now also applies to the Counter class (or instance). To denote the relationship between the two classes, State is called a superclass of Counter, and Counter is a subclass of State.

The methods inherited from State include the alloc method and we can now send alloc messages to the Counter class to create new Counter instances:

Counter count1 = [Counter alloc];

The return type of the alloc method is instance (id). The id type denotes the type of the receiving object, as seen by the caller. In the example, the receiver is the Counter class object, and id denotes the Counter class. The instance () modifies the type between the parentheses to indicate the instance of that type. The type of object returned by the alloc method in this example thus is `instance of the Counter class', written as Counter, which is exactly the type of the count1 variable to which the value returned is assigned.