TOM
 
The selector type
 
 
TOM Home
TOM Tasks

FAQ
News
Highlights
Publications
Documentation
Download TOM
TOM Software
Bug Database
Mailing Lists

Mail:
tiggr at gerbil.org

Short Cuts:
Tesla
TOM/Gtk
GP
MU

Snapshots:
all of 'em
tom [an error occurred while processing this directive]
tesla [an error occurred while processing this directive]
mu [an error occurred while processing this directive]
tomgtk [an error occurred while processing this directive]

Released:
all of 'em
tom 1.1.1
tomgtk 0.11
tesla 0.91
gp 0.5
mu 1.0

Misc:
GIF free NOW!

Suppose I have this object o which is an instance of class MyClass:

MyClass o = ...;
To invoke the multiply by method of this object, I could write:

int result = [o multiply 6 by 9];
In this example, the multiply by method is invoked with the int arguments 6 and 9, and the int that is returned is assigned to the variable result.

A method invocation can also be explained as sending a message to an object. In the example message being sent, the receiver of the message is the object o and the arguments of the message are 6 and 9. The message is completed with a selector: the selector indicates the intention of the message. In the example, the selector contains the information to `perform a multiply by with int arguments 6 and 9, returning an int'.

When this message is sent, the method indicated by the selector, as implemented by the receiver, is invoked. Thus, sending a multiply by message will invoke the multiply by method. Of course, the argument and return type information of the selector is significant in the selection of the method: a method returning a int is different from one returning a float, a difference that can be also be discerned in the corresponding selectors.

Resuming, a selector is a name for behavior. Upon sending a message, this name is bound to an implementation of that behavior, i.e. a method. Now, why is the selector an important type? Precisely because it is only a name: it is not bound to a particular object and has no relation to any implementation.

For example, suppose you have a collection of objects, and you want to invoke a method on each of the objects. If the collection is an array, things are easy:

int i, n = [array length];
for (i = 0; i < n; i++)
  [array[i] doSomething];
But, the collection need not be an array; it could be a collection of any kind, and using a loop like in the example, to walk along the elements, will not work in the case of a general collection. Suppose the collection provides the functionality to invoke a method on each of the objects it contains. In this case, using C++ as an example, one would pass a function pointer to the method (member function) to be invoked. However, if that method is a virtual method, and the objects in the container provide different implementations, the wrong method will be invoked!

The selector type solves this problem. In the case of an array, the method to have elements of the array perform some method, could look like this:

void
  makeElementsPerform selector a_method
{
  int i;

  for (i = 0; i < length; i++)
    [self[i] perform a_method];
}
Now the method invoked on every object will be the proper method, obeying the rules of method invocations (and the rules of the C++ virtual keyword; in TOM, every method is virtual by definition).

Obviously, this example is only a simple example. The avid reader will immediately ask `and what about arguments to be passed to the elements?' This will be discussed in a future TOM Highlight. To provide a hint: a method invocation can be put in an Invocation object.


Up: Highlights
 
Copyright © 1997-2002 Programmers Without Deadlines