It often seems as if objects appear by "magic." It is more reasonable to say they are provided by the Swarm library in a way that is not entirely obvious. For example, suppose you want to create a list of objects. One can declare an object listOfFriends and then create it, like so:
id listOfFriends; listOfFriends = [List create: self]; |
You see little bits like this all over example code from Swarm projects. Where does this List class object come from? Why are you able to use it even though there is no import statement for List.h at the top of the program? It seems as though, if you want to make a call on the List class, you ought to include List.h at the top of your file, right?
To use many of the Swarm classes, it is not necessary to use such an explicit import statement since you are not subclassing. Instead, it is necessary to include one of the "general purpose" header files that corresponds to the major sections of the Swarm library. To create List instances, for example, one needs to import the "general purpose" collections.h, which declares not only List, but other collections classes as well.
The general purpose header files can be found in the include directory of your swarm installation. They are:
activity.h
analysis.h
collections.h
collections.h
gui.h
objectbase.h
random.h
simtools.h
simtoolsgui.h
space.h
As you browse the Swarm Reference Guide, you will find many protocols that adopt the CREATABLE protcol, which means that you can use them to create objects in your code. When you use them, import one of these library headers. For example, to create List objects, import collections.h. That header file should be included in any file that refers to a List, Map, Set, or any of the other creatable collections objects.
Should the general purpose header file be included in the .h (header) file or the .m (implementation) file of your class? Generally speaking, it is only necessary in the .m file, since that is where you are doing the work of creating the object. The only exception to this rule arises if you refer to the protocol protocol in your header file. It is necessary to include the collections.h in your header file if you want to declare an object that will adopt a protocol, as in
id <List> aList; |
If you forget to import collections.h, the compiler will fail and say there was a parse error. This happens because it does not have a class or protocol List in its purview, and so it assumes you have made a typographical error.
On the other hand, if your header file uses a general declaration, as in
id aList; |
Explicit importing of a class-specific header file is only required when you need to subclass from that file. Since your header file declares that you are creating a class, and it defines the superclass, then the import statement must be included in your header file. SwarmObject is the most frequently used superclass, so consider it for example. Your class's header file should import both the general purpose library header objectbase.h as well as objectbase/SwarmObject.h
We will summarize this by offering two rules of thumb:
if you use a class that conforms to a protocol (such as List) to create objects in your own program, you need to include one of the general Swarm library headers.
if, however, you are subclassing from a class that adheres to a protocol, you need to import the header file for that class.
As good coding practice, you should try to keep your files clean. Each file should only include imports for header files that you actually reference in that particular interface/implementation file pair. Don't adopt a "include everything" mentality when importing files.