Object Oriented Programming in Script/Classes
Author: Jeff Stephenson
The first step in any object-oriented programming project is to define the classes which will be used in the project. Generally there is already a large library of classes to draw on (in this case the classes documented in Script Classes for Adventure Games), and often these classes are all one will need in the project. However, in order to define new classes and to understand the old ones, it is necessary to understand the class statement for defining a class.
The form of the class statement is:
Code:(class aClass kindof superClass (properties aProperty value ... ) (methods aMethod ... ) (method (aMethod [p1 p2 ...] [&tmp t1 t2 ...]) code ) ... [(procedure ...)] )
This statement defines aClass as a sub-class (kindof) superClass. This means that it inherits all of superClass' properties and methods, and will either modify or add to them. In order for the sc compiler to compile this class definition, superClass must either have been defined earlier in the current source file or in another file which will be compiled before this file will be compiled, adding the super-class definition to the file classdef (more on this at the end of this section).
The properties section of the class statement is where new properties are introduced and old default property values redefined. All entries in this section are of the form aProperty value where aProperty is a symbol and value is a constant expression. If aProperty is not a property of superClass, it is added as a new property in the class being defined and its default value is value. If the property exists in superClass, its default value for the class being defined is just changed to value.
The methods section of the class statement lists any symbols which will be the names of methods added to superClass to create the class being defined. Listing a method which is already defined in superClass does nothing, and a method name need not be listed in the methods section if it is only being redefined.
The method statement in the class statement is almost identical to the procedure statement described in The Script Programming Language. It differs in that the properties of the class in which the method is defined can be accessed as if they were variables, i.e. by simply using their names. Also, code in a method definition is the only place in which sends to the objects self and super are valid. Only methods inherited from the superclass or listed in the methods section may be defined. As in procedures, the compiler-defined variable argc gives the number of parameters passed to the method.
Note that procedures may also be included in a class statement. These procedures can be used by the methods defined within the class, but cannot be accessed from outside the class definition.
Source files containing class definitions are compiled with the sc compiler just like any other source file. There are some subtleties involved where class definitions are concerned, however, arising from the fact that all sub-classes of a class must be defined after the class' definition. Thus the order of source file compilation is very important -- the files containing the lowest level classes (such as Object) must be compiled first, followed by successive sub-classes. An understanding of how the compiler maintains information on all the classes will clarify how the class compilation process works.
Two files, classdef and selector constitute the database in which the compiler tracks the classes being defined. The first thing that the compiler does when compiling a file is to read in the file selector, which defines the symbols which are known to be selectors and the selector numbers corresponding to them. From this it also obtains the largest selector number currently defined, which will mark the point from which it will assign new selector numbers when they are needed. If you are compiling on a network, this file will be locked when you start compiling. This prevents anyone else from starting a compile (and possibly changing the information in the database) while you are using it.
The compiler next reads the file classdef (if it exists), from which it obtains information about the classes which have already been compiled. The information in classdef includes the class number (assigned by the compiler), the number of the script in which it is defined, the class number of the class' super-class, the names of the class' methods, and the names of the class' properties with their default values.
The compiler now gets around to reading your source code. As the compiler encounters each class definition, it records in its class symbol table the characteristics of the class. If the class already has an entry in the symbol table because it has been previously defined, that entry is cleared and the class is redefined using the current source code. This guarantees that the compiler is always using the most current class definition.
The class definition is built from the information contained in the methods and properties sections -- the selectors encountered here are added to those inherited from the class' super-class to arrive at the structure of the class being defined. Any symbol encountered in a properties or methods section of a class definition is looked up in a special symbol table for selectors. If it is not present there, it is entered in the selector table and assigned the next available selector number. Symbols are also entered in the selector symbol table if they are undefined symbols encountered in the position which a selector would occupy in a message to an object.
Assuming that the source file compiles with no errors, the compiler rewrites classdef and selector from its class and selector symbol tables. On multi-files compilations this is done after each successful compilation. The external database is thus kept as up-to-date as possible. Along with these files, the compiler rewrites classtbl and vocab.001 after each successful compilation. Classtbl is a table which gives the script number in which each class is defined, and is used by the kernel to load the appropriate script when a class is referenced. Vocab.001 is a file which contains the names of all the selectors in a format which can be used by the kernel to display selector names in error and debugging messages.
At the start of a project, you start with no classdef file and a selector file which is a copy of the file selector.new. The latter file contains the definitions of those selectors which the kernel needs to know about and which thus must have particular numbers. As you compile files, beginning with system.sc, the files classdef and selector grow with the addition of new classes and selectors. This growth is a one-way street, though -- nothing you do to your source code will cause a class or selector to be removed from these files. Thus, by the end of the project you are likely to have a number of obsolete classes and selectors hanging around in the database. To winnow the chaff from these files you should, near the end of the project, delete classdef, copy selector.new over your existing selector, and recompile all your files (in the proper order, of course!). This leaves you with a class/selector database with only those classes and selectors which you are using.