Another useful method is STRING. The STRING method is a handy 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. In doing this, 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.
Let's look at two programs that 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
On 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. (We'll see how to create an instance of a class in
the next program.) Our 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.
Instances in the Part class
┌───────────────────
│
│
Part class
part instance
(name='Widget')
(description='A small widge')
(number=12345)
part instance
(name='Framistat')
(description='A device to control frams')
(number=899)
part instance
(name='Defragulator')
(description='Removes frags from framistats')
(number=01045)
INIT expects to be passed three arguments. The USE ARG instruction assigns these three arguments to the name, description, and number variables, respectively. Since 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 doesn't expect any arguments. It uses the EXPOSE instruction to tap into the object variables. The RETURN instruction returns the result string.
Now let's see 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.
Next, look at the two assignment statements for MypartA and MypartB. These assignment statements 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. Our 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, as we mentioned earlier, 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. Recall that you don't 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.