Intro To OO Programming For COBOL Developers
Intro To OO Programming For COBOL Developers
Introduction
Micro Focus
The Lawn
22-30 Old Bath Road
Newbury, Berkshire RG14 1QN
UK
http://www.microfocus.com
MICRO FOCUS, the Micro Focus logo and Visual COBOL are trademarks or registered
trademarks of Micro Focus or one of its affiliates.
2021-11-05
ii
Contents
An Introduction to Object-Oriented Programming for COBOL Developers
............................................................................................................................. 4
Classes and Methods ..........................................................................................................4
Objects ................................................................................................................................ 7
Creating an Instance of a Class .......................................................................................... 7
Constructors ........................................................................................................................8
Properties ............................................................................................................................9
Types and Members ..........................................................................................................10
Member Visibility ............................................................................................................... 10
Local Data ......................................................................................................................... 11
Data Types ........................................................................................................................ 11
Inheritance ........................................................................................................................ 12
Interfaces .......................................................................................................................... 15
Class Names .....................................................................................................................16
Intrinsic Types ................................................................................................................... 17
The .NET and JVM Frameworks .......................................................................................18
Calling COBOL From Other Languages ........................................................................... 20
What Next? ....................................................................................................................... 23
Contents | 3
An Introduction to Object-Oriented
Programming for COBOL Developers
Overview
This guide provides a basic introduction to Object-Oriented Programming (OOP) for COBOL developers
who use Micro Focus Visual COBOL or Micro Focus Enterprise Developer. There are sections in the guide
for each of the key concepts of object orientation.
Managed COBOL, which is the collective term for .NET COBOL and JVM COBOL, is regular procedural
COBOL with extensions to take advantage of the features of the managed frameworks. This includes
object-oriented syntax (OO) that allows access to large libraries of functionality you can use in your
application and much more. To take full advantage of managed COBOL, you need to understand the
object-oriented concepts.
Sample code
This guide includes a number of pieces of sample code to illustrate some of the concepts of object-
orientated programming in COBOL. As you read the guide, you might want to type the code yourself,
compile it and step through it in the debugger in Visual COBOL or in Enterprise Developer.
You need one of the following products installed:
• Micro Focus Visual COBOL for Visual Studio
• Micro Focus Visual COBOL for Eclipse for Windows
• Micro Focus Enterprise Developer for Visual Studio
• Micro Focus Enterprise Developer for Eclipse
Note: Visual COBOL and Enterprise Developer cannot co-exist on the same machine.
To run the examples, create a JVM COBOL project in Eclipse or a .NET COBOL console application in
Visual Studio.
At the heart of the Object-Oriented Programming is the notion of a class. A class is said to encapsulate the
information about a particular entity. A class contains data associated with the entity and operations, called
methods, that allow access to and manipulation of the data. Aside from encapsulation of data, classes are
also very useful for bridging your existing procedural programs with managed code technologies.
Here is a simple COBOL class:
class-id MyClass.
linkage section.
end class.
Before we look at the details of the class, let's see how you would invoke the single method that it contains:
program-id. TestMyClass.
procedure division.
end program.
Note: To run this example in Visual Studio, you need to specify a Startup object for your .NET COBOL
console application. To do this:
1. In Visual Studio, right-click the solution in Solution Explorer.
2. Click Add > New Item, and click COBOL class.
3. Specify a name such as MyClass.cbl, and click Add.
4. In the same way, add a COBOL program with the name TestMyClass.cbl.
5. Add the two pieces of the example code above to the class and to the program, respectively.
6. Click Project > ProjectName Properties and click the Application tab.
7. Set Startup object to TestMyClass:
procedure division.
end program.
Visual COBOL simplifies aspects of the COBOL language - let's look at a couple of cases in our example:
invoke type MyClass::SayHello(by value "Peter")
Can become:
invoke type MyClass::SayHello("Peter")
If the method contained further arguments, these might appear as:
invoke type MyClass::SayHello("Peter", 37, "Bristol Street")
In fact, even the commas separating parameters are optional.
In future examples, we will use this abbreviated syntax.
The method can also be simplified as follows:
method-id SayHello static.
linkage section.
01 your-name pic x(10).
procedure division using by value your-name.
display "hello " & your-name
end method.
Objects
Our simple example so far has helped demonstrate the basic concept of a class but the value of Object-
Oriented Programming is not yet apparent. The power of Object-Oriented Programming really comes into
play when we encapsulate data within a class, provide methods that perform actions on that data, and then
create instances of the class for use at run time.
Creating an instance of a class results in the creation of an object. Each object maintains a separate set of
data items that the methods act upon.
You can create many instances of a class so, therefore, you can have many objects, each with data distinct
from other objects in the system. This data is called instance data.
For example, if we considered the kind of data we might need in a simple bank account class, we might
think of such things as an account number, balance and some way in which we could store transactions. At
run time, we could conceivably create a unique object for each customer we were dealing with where each
object maintains distinct data from other customers at our bank.
Let's change our class a little and look at how we would create an object instance:
class-id MyClass.
working-storage section.
01 your-name pic x(10).
method-id SayHello.
procedure division.
display "hello" & your-name
end method.
end class.
The variable your-name defined in the working-storage section is the instance data for this class:
working-storage section.
01 your-name pic x(10).
end program.
This is the declaration of the object, more formally known as an object reference:
01 an-obj type MyClass.
If we were to try and invoke the SayHello method on this object at this point, we would get a run-time
system error because the object has not yet been created.
This is the line that creates the object:
set an-obj to new MyClass
The keyword NEW is responsible for creating our object. NEW requires we specify the type of the object
we want to create. This may seem strange as we have already said what type our object is when we
declared it, but later on we will see that an object can be declared as one type but, at run time, reference a
different type.
When a class is instantiated in this way, the object is created in the object heap, which is a memory area
managed by the .NET or the JVM system. A reference to this object is then set up in the data item an-obj.
When no more references to the object exist (i.e. an-obj has been set to null, or to point to some object,
and the same applies to any other references), then the system may remove the object so that the memory
space can be reused. This process is known as garbage collection.
The SET statement is frequently used in Object-Oriented Programming and is synonymous with move but
applies to objects as well as indexes and other existing features of the COBOL language.
It is possible to declare another object reference and assign it the value of an-obj as follows:
set another-obj to an-obj
In this case, another-obj now contains the same reference as an-obj. It is important to note that while we
have two object references, there is actually only one instance of type MyClass at this point, and both
another-obj and an-obj refer to it. If we invoked the SayHello method on an-obj and another-object, they
would operate against the same instance data in the working-storage section.
The only way to create an entirely new object of type MyClass is to use the NEW keyword:
set another-obj to new MyClass
Our class has an issue at the moment. If we were to invoke the SayHello method, it would just print Hello,
as the your-name data item has yet to be given a value.
There are several ways we can fix this. One way to do this is during the creation of the object which is
otherwise known as construction. Right now, our class does not do anything during construction, but we
can do so if we create a method named New.
Constructors
method-id New (a-name as string)
set your-name to a-name
end method.
Method Overloading
However, it is possible to have multiple versions of the New method, each corresponding to different
arguments that can be passed in when the object is created. This is called method overloading because
the method name remains the same but different arguments are accepted by each method.
We can also use this ability of method overloading to reinstate the so-called default constructor, otherwise
known as the parameterless constructor. To do so, we just code a new New method.
method-id New.
move all 'x' to your-name
end method.
This has allowed us to create the object by either supplying a parameter or using the default constructor
which takes no arguments but still allows us to initialize our working-storage section data.
Alternately, these two constructor variants can be combined using an optional parameter. An optional
parameter is one where a default value has been supplied by means of the syntax '= value'. In this
example, the constructor could be coded:
method-id New (a-name as string = "x")
set your-name to a-name
end method.
If the constructor is called without an explicit parameter, a value of "x" is supplied automatically.
Properties
Our class has some data associated with it, namely a string called your-name. This data is not accessible
directly by the program using the class just as the working-storage of one program is not accessible to
another program.
Properties allow you to expose your data items to the user of your class.
Currently, our single data item looks like this:
01 your-name pic x(10).
We can turn this data item into a property as follows:
01 your-name pic x(10) property.
As such, you can now access this property through an object reference:
display an-obj::your-name
The property keyword allows us not only to get the value of a data item, but also to set it:
set an-obj::your-name to "Peter"
Member Visibility
The methods and properties we have defined so far have all been public, which is the default for COBOL.
A public method means that it can be invoked through the object reference. However, for most classes we
need methods which we do not want to be visible outside of the class. Such methods are called private
methods.
To declare a private method, use the keyword private:
method-id ProcessData private.
This method cannot be invoked from outside the class itself and, if you tried, you would receive a Compiler
error.
You can invoke this method from inside the class itself, say, from inside a public method:
method-id DoSomething public (a-name as string).
invoke self::ProcessData
end method.
Local Data
When working with classes, the working-storage section following the class-id header is used for instance
and static data, but we can also define data that is used only by a method, or so-called local data.
There are three ways to define local variables:
In the Local- In the following example, mylocalvar is a local variable for the method and it only
Storage Section exists for this method:
method-id ProcessData private.
local-storage section.
01 mylocalvar binary-short.
procedure division.
...
end method.
Using the In the following example, mylocalvar is defined using the DECLARE statement. The
DECLARE scope of the variable defined in this way is only within the method after the
statement declaration:
method-id ProcessData private.
declare mylocalvar as binary-short
end method.
Define as an In the method, we can create a local variable called counter as part of the PERFORM
inline statement. The lifetime and scope of this variable is associated with the execution and
variable scope of the PERFORM statement. In other words, it is not possible to refer to counter
after the END PERFORM statement.
method-id ProcessData private.
perform varying counter as binary-long from 1 by 1 until counter > 10
display counter
end-perform.
end-method.
Data Types
So far, our classes have used COBOL data types such as pic X. All of the data types you use in procedural
COBOL today are supported in managed COBOL.
Inheritance
working-storage section.
01 account-number pic 9(8) property as "AccountNumber".
01 balance float-long property.
end method.
*> Specialized process for Savings withdrawal.
end class.
Besides defining a new class for savings accounts, we have used the inherits clause to denote we are
extending an existing class in the system. All public and protected members (methods, properties, fields
defined as public or protected) of the base class become part of the new class.
As such, an object that is of the type SavingsAccount, also has properties called AccountNumber, balance
and a method named Withdraw which have been inherited from the base class BankAccount.
Our SavingsAccount class also has a method called Withdraw which will manage the different way in which
money is withdrawn from a savings account. To indicate this is a change in behavior to the method in the
base class, we use the override keyword. The significance of this keyword will become more apparent later
on.
Let's create another specialization of the BankAccount class, a debit account:
class-id DebitAccount inherits BankAccount.
end class.
This class for debit accounts is created in exactly the same way as the class for the savings account. It
extends the bank account class and all public members of the bank account class become part of the new
class.
The DebitAccount class also has a Withdraw method that overrides the Withdraw method of the
BankAccount class, and it defines how money is withdrawn from the debit account. This method, however,
is a completely different one from the Withdraw method in the SavingsAccount class.
We now have three classes in our class hierarchy - one base class (BankAccount) and two classes
(SavingsAccount and DebitAccount) that are derived from it, each of which provide a different override for
the Withdraw method.
procedure division.
end method.
In this case, a method receives an argument of type BankAccount from which it performs a withdrawal
action. The method does not need to know about all the different types of accounts but, whichever object
type is passed in, the correct Withdraw method associated with that type is executed, be that a savings or
debit account.
We can invoke that method with an argument of either account1 or account2:
invoke SomeClass::PerformWithdrawal(100,account1)
invoke SomeClass::PerformWithdrawal(200,account2)
We've passed account1 and account2 and for each one of them, the appropriate Withdraw method
associated with SavingsAccount and DebitAccount is executed.
This is a very useful feature of Object-Oriented Programming as it decouples implementation details from
clients that use the classes. This, in turn, allows us to extend the system by adding new types of bank
accounts but minimizing the impact on existing code.
Under both JVM and .NET, you can only inherit from one base class but, of course, the base class itself
can inherit from a class and so on.
If a derived class needs to invoke the implementation of a method defined in the base class, it can do so
using the super keyword. For example, we can call the BankAccount WithDraw method from within the
SavingsAccount class as follows:
invoke super::Withdraw(100)
super can be used not only to invoke a method we have overridden in the derived class, but also to invoke
any public method defined in the class hierarchy we have inherited.
Classes and inheritance allow us to decouple implementation details from the user of the class but there is
another aspect of Object-Oriented Programming that can help further decouple implementation - the
interface.
An interface, like a class, defines a series of methods and possibly data, too, but unlike a class, it does not
provide any implementation within the methods. This is because the purpose of the interface is merely to
define what behavior a class will have - behavior in this case being the methods and properties defined on
the class.
Here is an example of an interface:
interface-id ErrorHandler.
end interface.
This interface defines just two methods which we can probably deduce would be used for logging an error
of some kind.
By defining a class that supports this interface, we are said to implement the interface:
class-id MyErrorHandler implements type ErrorHandler.
end class.
The implements keyword defines the interface we intend to provide an implementation for in this class and
the Compiler will check that all methods have been implemented correctly.
Unlike inheriting a class, which can only be done with a single class, you can implement as many
interfaces as you like in a single class.
We can create an instance of our class and because we have implemented the ErrorHandler interface, we
can pass an object reference of this class to any code that expects to be working with the ErrorHandler
interface.
class-id ProcessData.
working-storage section.
method-id DoProcessing.
declare error-code as binary-short = 1
*> do something and, possibly, call NotifyErrorHandlers when something
*> goes wrong
*> ...
invoke self::NotifyErrorHandlers(error-code)
*> ...
end method.
end class.
program-id. TestProgram.
working-storage section.
01 error-handler type MyErrorHandler.
01 processData type ProcessData.
procedure division.
Class Names
So far, our classes have had simple names but this can soon lead to clashes with classes created by other
people. To resolve this, we simply create classes with longer names by employing the use of namespaces
which is nothing more than a convention for naming classes.
Intrinsic Types
The COBOL Compiler is aware of several classes within the .NET and the JVM frameworks and does not
require you to specify their fully qualified names. The two classes we will look at are Object (System.Object
in .NET and java.lang.Object in JVM) and String (System.String in .NET and java.lang.String in JVM).
Object is important because all classes ultimately inherit from this type, whether you specify it or not.
Therefore, any object can be cast to this type.
String is used commonly for storing Unicode data. In both JVM and .NET, the string, once created, is
considered immutable. Instance methods in the String class may return new strings derived from the
current string (e.g. a substring), but the original string is itself never changed.
01 str1 type System.String.
01 str2 String.
01 str string.
All of the above declarations in .NET are equivalent.
Notice there is no need to call the New method when creating a string:
set str1 to "Hello World"
You can combine strings with regular pic X fields as follows:
01 a-pic-x pic X(10) value "something".
display a-pic-x & str1 & "blah"
.NET and JVM are huge frameworks of classes that provide a massive range of functionality. Learning all
the classes in these frameworks can take a long time but there are many classes that you should get to
know quickly, particularly the collection classes.
To help illustrate the usefulness of these frameworks, let's look at just one area - date and time arithmetic
made easy with the following example in .NET COBOL:
working-storage section.
display ts
Let's review what we have done.
First of all, we have declared three object references, two DateTime objects and one TimeSpan object.
The DateTime class provides an extensive set of routines for manipulating dates and times. To get an idea
of its capabilities, see the description of the class on Microsoft's MSDN.
The TimeSpan class is used when calculating the difference between two DateTime objects.
In the first line of code, we initialize the dt1 object reference using a static method on the System.DateTime
class, Now. There are many other ways to initialize a DateTime object but this is a convenient way of
getting the current date and time:
set dt1 to type System.DateTime::Now
On the next line, we again make use of a static method, this time to cause the current thread to sleep for a
specified number of milliseconds. You could invoke the Micro Focus CBL_THREAD_SLEEP routine to
achieve the same result.
The next line initializes our second DateTime object following the sleep:
set dt2 to type System.DateTime::Now
The next line demonstrates a feature of the managed code COBOL Compiler called operator overloading:
set ts to dt2 - dt1
data division.
working-storage section.
01 start-time binary-double.
01 end-time binary-double.
01 interval binary-double.
01 hr binary-double.
01 min binary-double.
01 sec binary-double.
01 ms binary-double.
procedure division.
goback.
linkage section.
01 your-name pic x(10).
procedure division using by value your-name.
end class.
Because managed COBOL follows the rules of any other managed language, you can invoke its methods
from other managed languages.
your-name is a PIC X item and is exposed as a string when used as a by value parameter.
You can invoke the SayHello method from a C# project provided that you have set a project reference in
your C# project to the COBOL project. To do this:
1. In your solution, create a C# project and add a reference to the COBOL project:
a. In Solution Explorer, right-click the C# project and click Add Reference.
b. On the Project tab, select your COBOL project, and click OK.
2. In the same way, add a reference in the C# project to the Micro Focus Runtime assembly - in the Add
Reference dialog, click the .NET tab, select Micro Focus Runtime, and click OK.
3. In the C# program, type the following to invoke the COBOL class:
...
class MyCSharpClass
{
static void Main(string[] args)
{
MyClass.SayHello("MyName");
}
}
To do the same from Java:
1. In Visual COBOL for Eclipse, create a COBOL JVM project, MyCOBOLProject, and a Java project,
MyJavaProject.
2. Create a new COBOL JVM class in your COBOL project, MyClass, and assign it to the default package.
3. Paste the COBOL code of the simple class to the class file.
linkage section.
01 your-name.
03 first-name pic x(10).
03 middle-name pic x(10).
03 surname pic x(10).
01 your-address.
03 street-name pic x(10).
03 town-name pic x(10).
03 country-name pic x(10).
linkage section.
01 your-name.
03 first-name pic x(10).
03 middle-name pic x(10).
03 surname pic x(10).
01 your-address.
03 street-name pic x(10).
03 town-name pic x(10).
03 country-name pic x(10).
What Next?
This guide provides a basic introduction to Object-Oriented Programming and has covered many of the
fundamental concepts. Object-Oriented Programming is, however, an extensive subject, and there are
many other areas to cover including the many technologies provided by the .NET and JVM platforms. Now
that you know the basics, you can continue with the advanced topics.
For further reading on Object-Oriented programming, we recommend you check the following Web sites:
• For programming for the .NET framework, see .NET Framework 4 on the MSDN.
• For JVM programming, see Learning the Java Language on the Oracle Web site.
Various demonstrations of managed COBOL are available with Visual COBOL and Enterprise Developer.
To access the demonstrations, open the Samples Browser from the Start menu group of the product - click
Samples for Visual COBOL, or Samples > Visual COBOL Samples for Enterprise Developer.
The Getting Started section in your product help offers a number of tutorials on programming using
managed COBOL.
Aside from additional self-study, you should also consider a dedicated training course in C#, Visual Basic,
or Java. These courses will build upon your knowledge of Object-Oriented Programming and enable you to
build applications in C#, Visual Basic, Java, or COBOL as the principles remain the same across all of
these languages - the key difference being syntax.
A great way to accelerate your understanding of Object-Oriented Programming and managed code
frameworks is to work directly with colleagues skilled in C#, Visual Basic, Java or COBOL.
C
N
class
creating an instance of 7 namespaces 16
naming conventions 16 NEW 7
COBOL
calling from other languages 20
construction 7
O
constructor 8 object
creating 7
D object reference 7
objects 7
data types 11 operator overloading 18
DECLARE 11 OVERRIDE 12
default constructor 8
delegate-id 10
display 18 P
package name 16
E parameterless constructor 8
enum-id 10 predefined types 11
private method 10
properties 9
F public method 10
framework
.NET 18
JVM 18
S
further reading 23 SELF 10
SET 7
I static method 4
string 4, 17
ilusing 16 SUPER 12
IMPLEMENTS 15
inheritance 12
INHERITS 12 T
inline variable 11
instance data 7 TYPE 4
interface 15 types and members 10
intrinsic type 17
INVOKE 4 U
J USING 4
JVM framework 18
V
L valuetype-id 10
list 15
local data 11
M
managed COBOL 4
24 | Index