3.5. A Brief Clarification: Classes and Protocols in Objective C

There is one additional complication that readers should be aware of. Objective C allows the creation of entities called protocols. A protocol, as readers will recall from their study of Objective C, is a list of methods that an object is able to execute. Swarm is structured by protocols, which means that there are lists of methods assigned to various names and classes inside the library "adopt" those protocols and then implement the methods listed in the protocols. Hence, in the Swarm Reference materials present the libraries as a collection of classes, each of which adheres to a given set of protocols.

To the Swarm user, the distinction between class and protocol is not vital most of the time. The most important Swarm protocols, such as the type Swarm (from objectbase/Swarm.h) or SwarmObject (from objectbase/SwarmObject.h), can be used as if they were classes. In the Swarm Reference Guide, there is a list of all protocols. The protocols that adopt the CREATABLE protcol are the ones that users can use as if they were factory objects. For example, the EZGraph protocol adopts the CREATABLE protocol, so when the user needs to create an instance, so the observer swarm file can use the EZGraph to create graphs.

Almost all of the Swarm protocols adopt the CREATABLE protocol, so they can be used as if they were classes from which users subclass to make model swarms or individual agents. It should not matter to the user that these are abstract defined types that have adopted protocols (taken on the obligation to implement methods listed in protocols). The class SwarmObject, for example, adopts protocols Create and Drop as well as CREATABLE. This means that the user can act as if there is a class called SwarmObject, and that the SwarmObject will be able to respond to class methods like createBegin, and that instances created by SwarmObject will be able to respond to createEnd, drop, or any other method that is listed in a protocol listed by SwarmObject.

One of the principal advantages of protocol usage is that there will be compile-time warnings if the user's code tries to send a "bad message" to an object. If a message tells an object to goOutside, and none of the protocols adopted by that agent have a method called goOutside, then the compiler will warn the user about it. In a crude way, adopting a protocol is like advertising that a class can do certain things, and the compiler enforces a `truth in advertising' policy. If the compiler flags include -WERROR, causing all warnings to be treated as errors, then these warnings will stop the compilation.

The fact that many of the important components of the Swarm library are organized as protocols can, however, be important in some notation. Early versions of Swarm had less emphasis on protocols than the current version. As a result of the introduction of protocols, usage conventions have changed. In Swarm, there is a class List that can be used to create collections. In the "old days" of Swarm, one would create a statically typed object of class List, as this code indicates:

List * listOfPuppies;
listOfPuppies=[List create: [self getZone]];

Swarm no longer allows users to statically allocate objects in this way. This code will make the compiler crash, because there is no class inside Swarm called List, there is only a protocol. The compiler will fail, and the user will get a vague warning about a parse error in the vicinity of the List usage.

We know from the Swarm Reference Guide that the List protocol advertises that it adopts the CREATABLE protocol, so the mistake is not in the usage of List to create the listOfPuppies. Rather, the mistake is in the declaration of the listOfPuppies itself. If one needs to define a variable listOfPuppies that has the properties of a List class item, the recommended approach is to create a variable of type id and indicate the protocols adopted by that object in brackets:

id < List >  listOfPuppies;
listOfPuppies=[List create: [self getZone]];
      

It is also legal to define listOfPuppies as a generic object, as in

id listOfPuppies;
listOfPuppies=[List create: [self getZone]];

This usage is legal, and the program should compile without difficulty. The only shortcoming is that the user will not be warned if the listOfPuppies object is sent any inappropriate messages within the program. When these inappropriate messages are sent during the run, then the program will crash, possibly with a message that the object listOfPuppies does not respond to the message it was sent.

Since almost all of the important pieces of functionality in the Swarm library are now written in the protocol format and are CREATABLE, these details may be important. However, these details do not significantly change the way applications are designed. Swarm entities can still be treated as classes.