When running your program, three methods that Rexx looks for, and runs automatically when appropriate, are INIT, UNINIT, and STRING.
Object classes can create instances. When these instances require initialization, you'll want to define an INIT method to set a particular starting value or initiate some startup processing. Rexx looks for an INIT method whenever a new object is created and runs it.
The purpose of initialization is to ensure that the variable is set correctly before using it in an operation. If an INIT method is defined, Rexx runs it after creating the instance. Any initialization arguments specified in the NEW or ENHANCED message are passed to the INIT method, which can use them to set the initial state of object variables.
If an instance has more than one INIT method (for example, INIT is defined in several classes), each INIT method must forward the INIT message up the hierarchy and run the topmost version of INIT, to properly initialize the instance. An example in the next section demonstrates the use of INIT.
The STRING method is a useful way to access object data and return it in string form for use by your program. When a SAY instruction is processed in Rexx, Rexx automatically sends a STRING message to the object specified in the expression. Rexx uses the STRING method of the Object class and returns a human-readable string representation for the object. For example, if you instruct Rexx to say a, and a is an array object, Rexx returns an array. You can take advantage of this automatic use of STRING by overriding Rexx's STRING method with your own, and extract the object data itself--in this case, the actual array data.
The following programs demonstrate STRING and INIT. In the first program, the Part class is created, and along with it, the two methods under discussion, STRING and INIT:
/* PARTDEF.CMD - Class and method definition file */ /* Define the Part class as a public class */ ::class part public /* Define the INIT method to initialize object variables */ ::method init expose name description number use arg name, description, number /* Define the STRING method to return a string with the part name */ ::method string expose name return "Part name:" name
In the ::CLASS directive, the keyword PUBLIC indicates that the class can be shared with other programs. The two ::METHOD directives define INIT and STRING. Whenever Rexx creates a new instance of a class, it calls the INIT method for the class. The sample INIT method uses an EXPOSE instruction to make the name, description, and number variables available to other methods. These exposed variables are object variables, and are associated with a particular instance of a class:
INIT expects to be passed three arguments. The USE ARG instruction assigns these three arguments to the name, description, and number variables, respectively. Because those variables are exposed, the values are available to other methods.
The STRING method returns the string Part name:, followed by the name of a part. The STRING method does not expect any arguments. It uses the EXPOSE instruction to tap the object variables. The RETURN instruction returns the result string.
The following example shows how to use the Part class:
/* USEPART.CMD - use the Part class */ myparta=.part~new("Widget","A small widge",12345) mypartb=.part~new("Framistat","Device to control frams",899) say myparta say mypartb exit ::requires partdef
The USEPART program creates two parts, which are instances of the Part class. It then displays the names of the two parts.
Rexx processes all directives before running your program. The ::REQUIRES directive indicates that the program needs access to public class definitions that are in another program. In this case, the ::REQUIRES directive refers to the PARTDEF program, which contains the Part definition.
The assignment instructions for Mypart A and Mypart B create two objects that are instances of the Part class. The objects are created by sending a NEW message to the Part class. The NEW message causes the INIT method to be invoked as part of object creation. The INIT method takes the three arguments you provide and makes them part of the object's own exclusive set of variables, called a variable pool. Each object has its own variable pool (name, description, and number).
The SAY instruction sends a STRING message to the object. In the first SAY instruction, the STRING message is sent to MypartA. The STRING method accesses the Name object variable for MypartA and returns it as part of a string. In the second SAY instruction, the STRING message is sent again, but to a different object: MypartB. Because the STRING method is invoked for MypartB, it automatically accesses the variables for MypartB. You do not need to pass the name of the object to the method in order to distinguish different sets of object variables; Rexx keeps track of them for you.
Another way to define classes is by using the SUBCLASS method. You can send a SUBCLASS method to any desired superclass to create a class.
Object classes can create instances but have no direct control over their deletion. If you assign a new value to a variable, Rexx automatically reclaims the storage for the old value in a process called garbage collection.
If variables of other objects no longer reference an instance, Rexx automatically reclaims that instance. If the instance has allocated other system resources, you must release them at this time using an UNINIT method. Rexx cannot automatically release these resources because it is unaware that the instance has allocated them.
In the following example, the value passed to text is initialized by Rexx using INIT and deleted by Rexx using UNINIT. This program makes visible Rexx's automatic invocation of INIT and UNINIT by revealing its processing on the screen using the SAY instruction:
/* UNINIT.CMD - example of UNINIT processing */ a=.scratchpad~new("Of all the things I've lost") a=.scratchpad~new("I miss my mind the most") say "Exiting program." exit ::class scratchpad ::method init expose text use arg text say "Remembering" text ::method uninit expose text say "Forgetting" text return
Whether uninitialization processing is needed depends on the circumstances, for example when a message object holds an unreported error that should be reported and cleared. If an object requires uninitialization, define an UNINIT method to specify the processing you want.
If UNINIT is defined, Rexx runs it before reclaiming the object's storage. If an instance has more than one UNINIT method (for example, UNINIT is defined in several classes), each UNINIT method is responsible for sending the UNINIT message up the hierarchy, using the SUPERCLASS overrides, to run the topmost version of UNINIT.