In the Objects and Messages Tutorial you learned how to create instances of a class and send messages. In this chapter you will learn how to write classes for objects of your own, using the example Stopwatch class introduced in the Objects and Messages Tutorial.
The first part of the discussion looks at the way a class is built up. It is followed by sections in which you debug the Stopwatch code.
This tutorial consists of the following sessions:
This tutorial starts with a look at the overall structure of a class source element, using the Editor to examine the structure of Stopwatch.
The class source element consists of a set of nested source elements.
The sections below examine the following elements of the class source element:
To load Stopwatch into the Editor:
The Editor opens with stopwtch.cbl displayed. As you read the explanations in the following sections, use the Editor to locate and examine the code in stopwtch.cbl.
Each class source element starts with a class-id identifier and finishes with an End Class clause. These bracket the outermost level of the nesting. The Stopwatch class looks like this:
class-id. Stopwatch as "stopwtch"
inherits from Base.
...
end class Stopwatch.
The Inherits From phrase identifies Stopwatch's superclass, Base.
To see this code:
The Repository paragraph identifies the executable code files which implement classes used by the program. The superclass and every class which will be invoked from the class must be identified in the Repository paragraph.
To see the Repository paragraph for Stopwatch, scroll down the text edit pane until you get to the Repository paragraph, located below tag S005.
The Repository paragraph looks like this:
repository.
class Base as "base".
The Class clause serves two purposes:
A class is guaranteed to be loaded before the factory object receives its first message. Usually this occurs when you send the first message to the factory object, but before the factory object receives it.
The factory object source element defines the data and methods for the factory object. It is nested within the class source element, immediately following the class source element's Data Division (if there is one). It looks like this:
factory. working-storage section. * factory data . ... * factory methods end factory.
The factory object data is defined in the Working-Storage Section. The factory object data can only be accessed from the factory methods
Each factory method is a nested source element. The code below shows an outline for a "new" method for Stopwatch.
method-id. "new". ... linkage section. 01 lnkWatch object reference. procedure division returning lnkWatch. * code to create and initialize a Stopwatch object. exit method. end method "new".
As with the class source element itself, you can declare different types of data in the Data Division of the method. The Data Division header itself is optional. Data declared here is only accessible to the code in this method. The Data Division can contain any of the following sections:
Data items that are local to the current invocation of a method. The method uses local storage for all its temporary working data. This has the advantage of supporting recursion.
Variables passed as parameters to and from the method.
The Procedure Division contains the code for the method. You terminate processing of the method with an Exit Method statement. This returns processing to the program which invoked the method.
To see the "new" method, use the Editor to locate the "new" method, below tag S015. This method uses a Linkage Section to return data from the method.
The instance object source element defines the data and methods for instances of the class. It is nested within the class source element. It looks like this:
object. working-storage section. * instance data for the object. ... * Instance methods end object.
The only Data Division section that has any meaning in an object source element is the Working-Storage Section. You can create other data sections, but the run-time behavior if you try to access the data in these sections is undefined.
Any data you declare in the Working-Storage Section is accessible to all the instance methods, and may be inherited by instances of subclasses of the class.
There is no Procedure Division in an object source element, only methods. To write an initialization method for instances, write a method called "initialize", and then invoke it from the "new" method for the class after you have created an instance.
To see the object source element and data declarations paragraph for Stopwatch, use the Editor to locate the OBJECT header. The OBJECT header and Working-Storage Sections are located below tags S030 and S035.
Instance methods are nested inside the object source element. Writing an instance method is exactly like writing a factory method, with the only difference being the scope of data which the instance method can access.
The instance method can access data:
To see the "start" method for Stopwatch, use the Editor to locate the "start" method, just below tag S040. This method does not declare any data of its own, but makes changes to the object's state by altering data declared in the Working-Storage Section.
The code below summarizes the structure of a COBOL class, and recaps the material covered so far in this tutorial.
class-id. Stopwatch as "stopwtch"
inherits from Base.
*> Identification
*> and inheritance
repository. *> Repository paragraph names
*> the files containing the
class Base as "base" *> executables for each
*> class.
. *> Period terminates paragraph.
...
factory. *> Defines the start of the
working-storage section. *> Defines factory object data
...
method-id. "new". *> Start factory method "new".
...
end method "new". *> End factory method "new".
end factory. *> End factory object
object. *> Start the code defining
*> behavior of instances
*> of the class.
working-storage section. *> Defines instance data.
...
method-id. "start". *> Start instance
*> method "sayHello"
...
end method "stop". *> End instance method.
end object. *> End code for
*> instances.
end class Stopwatch.
This completes the summary of class structure. In the next section you will debug some of the Stopwatch code.
In this session, you will debug some of the code in the Stopwatch class, to see how classes and objects work. You are going to use the same programs as in the Objects and Messages Tutorial, but this time you will step through the code in Stopwatch so that you can see the code execute.
To debug the Stopwatch class:
This compiles timer.cbl and stopwtch.cbl.
The Debugger starts with the statement below tag T010 highlighted ready for execution.
This sends the "new" message to the Stopwatch class, and execution switches to the "new" method of the Stopwatch class.
The mechanism for actually creating a new object (allocating the memory and returning an object handle) is inherited from the supplied class library, and this statement executes the inherited method. Some classes do not implement the "new" method at all, but rely on the inherited method. Those that re-implement it usually do so to send an initialization message to the new object. In this case we have overridden it to keep track of the number of instances created.
Data item osCount is part of the factory data, which is declared in the factory Working-Storage Section.
Control switches to the "start" method of Stopwatch. Scroll up through the code to the OBJECT header (between tags S030 and S035). Methods which appear after the OBJECT header are instance methods, and can access data declared in the Working-Storage Section below the OBJECT header. They cannot access data declared in the factory object (between the FACTORY header and END FACTORY marker).
The "start" method tests to see whether the stopwatch is currently running, and if it isn't, stores the current time in working storage, in the startTime variable.
Control returns to timer.cbl.
This creates a second stopwatch without you having to step through all the "new" code a second time.
Execution switches to the "howMany" method of Stopwatch. This is a factory method (between the FACTORY header and END-FACTORY marker), and returns the value in factory data variable osCount.
Execution switches to the "start" method of Stopwatch.
When you executed this method previously, on step 9, you set watchRunning to true, but now it reads false. The reason is that each different instance of Stopwatch has its own unique data. The last time you executed this method, you sent the "start" message to the instance of Stopwatch represented by the handle in wsStopwatch1; this time you have sent it to a different instance, which has its own data.
Control returns to timer.cbl. At this point you have seen factory object and instance object code executing, and how different instances have different data.
You can debug the rest of the code if you are interested to see how the Stopwatch works.
This concludes this tutorial on writing a class. In this tutorial you learned:
The next tutorial demonstrates some more features of OO COBOL.
Copyright © 2009 Micro Focus (IP) Ltd. All rights reserved.