7.2. Detailed Look at createBegin/createEnd

Now take the next step and look at the createBegin and createEnd methods that are called by the code in main.m. Follow the steps into HeatbugObserverSwarm.m. Here you find the methods +createBegin and -createEnd. The plus sign on createBegin indicates that this method cannot be executed by an instance of the class HeatbugModelSwarm, but rather only by the factory object. Here is a portion of the method createBegin:

+ createBegin: aZone
{
  HeatbugObserverSwarm *obj;
  id <ProbeMap> probeMap;
  obj = [super createBegin: aZone];
  obj->displayFrequency = 1;

  // [Code that creates "probemaps" omitted here]
  return obj;
}

This a good example of how the Swarm toolkit handles the creation of objects. The pointer to the class HeatbugObserverSwarm named obj is defined. Since HeatbugObserverSwarm is subclassed from GUISwarm, it is important to be sure that all of the important variables of a GUISwarm object are initialized and inherited by HeatbugObserverSwarm. This is done in one step by telling the superclass to execute its createBegin method. Since the classes are linked together in a hierarchy, each higher level class in turn executes its createBegin statement. That is how the instance of the class ends up setting values for all the variables that it inherits.

The createBegin method of its superclass is called to put the created objects in aZone, which is the name of the space passed in from main.m. The memory zone that is created is returned and set equal to obj. Then the return obj command gives back the created object to the calling code, in this case main.m, which then treats it as theTopLevelSwarm.

The reader can investigate in the Swarm source code to see that GUISwarm inherits through a hierarchical chain the ability to create memory zones and objects. GUISwarm is subclassed from Swarm, which in turn inherits from CSwarmProcess. That class is defined in the activity directory of the source code in a file called SwarmProcess.m. This is the first place where you will find createBegin and createEnd methods as you move up the inheritance tree, so it must be that these are the methods that are executed when super is told to do something in this code.

The createEnd method in HeatbugObserverSwarm.m is quite simple:

- createEnd
{
  return [super createEnd];
}

In a case like this, when the super class is inside the Swarm library, it may be hard to figure out exactly why this command is needed. As a matter of fact, it is not necessary in this case at all, but it does not do any harm. If it were omitted from this class, then this class would just inherit createEnd method from the somewhere above in the family tree. By using it in this way, we make sure that the commands of the super class's createEnd method are executed, and this may be important because those steps might initialize some variables that this class inherits.

There are cases in which the createEnd statement may be more substantial. In the createBegin phase, we typically find commands that set permanent features of objects. Some methods that initialize instance variables can also be included. In the example above, the variable display frequency inside *obj is set equal to 1. These variables are set at the first possible opportunity because other variables may depend on them. After main.m calls the createBegin method, main.m may include statements that further tailor the state of the object and those commands may depend on values set in createBegin. Finally, when main.m calls createEnd, a new slew of commands may be executed that define further elements of the object.

The createEnd statement may be a convenient place to put any code that completes the initialization of an object. For example, suppose inside there is a variable called age. In createEnd, one might find this:

- createEnd
{
  [super createEnd];      
  age=0;
  return self;
}      

The super class's createEnd method is executed, which will assure that any variables initialized there are set properly. Then the instance variable age is set equal to 0. (Sometimes you will find examples in which createEnd is a "garbage can" that collects a large number of commands that set initial values for variables inside the object. These commands might as well be regrouped and put into a new method inside the object that might be called setInitialValues that would be executed after the createEnd. The readability of the code is enhanced that way.)

The create message causes the receiver to carry out both its createBegin and createEnd methods. Why didn't we always use create? Well, sometimes we need to define variables between the createBegin and createEnd steps, as seen in main.m. If there is no need to set values in that way (no methods are listed in the Creating phase in the Swarm Reference Guide are used), then create is enough.