Object-oriented programming (OOP) in COBOL was introduced in the COBOL 2002 standard, bringing modern programming paradigms to this venerable business language. OOP allows you to organize code using classes, objects, methods, and inheritance, making COBOL programs more modular, reusable, and maintainable.
Object-oriented programming is a programming paradigm based on the concept of "objects," which contain data (attributes) and code (methods). In COBOL OOP:
OOP in COBOL enables you to create more organized, maintainable code and integrate COBOL applications with modern Java-based systems.
Object-oriented COBOL offers several advantages:
Imagine you have a cookie cutter (that's a class). The cookie cutter defines the shape of cookies you can make. When you use the cookie cutter to make actual cookies (those are objects), each cookie might have different decorations or flavors, but they all have the same basic shape.
In COBOL, a class is like the cookie cutter - it's a template. When you create an object from a class, it's like making a cookie - you get something real you can use. Each cookie (object) can have its own decorations (data), but they all know how to do the same things (methods) because they came from the same cookie cutter (class).
If you have a special cookie cutter that's based on a regular cookie cutter but adds stars to it, that's like inheritance - the star cookie cutter (subclass) inherits the basic shape from the regular cookie cutter (superclass) but adds something extra!
A class is a blueprint that defines what data and methods objects of that class will have. An object (also called an instance) is a specific realization of a class - it has actual data values and can execute methods.
Think of a class as a cookie recipe and objects as the actual cookies you bake. The recipe (class) tells you what ingredients (data) and steps (methods) you need, but the cookies (objects) are the real things you can eat (use in your program).
123456789101112131415161718192021222324252627282930313233343536IDENTIFICATION DIVISION. CLASS-ID. Account AS "Account". ENVIRONMENT DIVISION. CONFIGURATION SECTION. REPOSITORY. CLASS java-lang-Object. DATA DIVISION. WORKING-STORAGE SECTION. OBJECT. DATA DIVISION. WORKING-STORAGE SECTION. 01 account-balance PIC S9(9)V99 COMP-3. 01 account-number PIC X(10). PROCEDURE DIVISION. METHOD-ID. get-balance. PROCEDURE DIVISION RETURNING balance AS FLOAT. MOVE account-balance TO balance GOBACK. END METHOD get-balance. METHOD-ID. deposit. LINKAGE SECTION. 01 amount PIC S9(9)V99 COMP-3. PROCEDURE DIVISION USING amount. ADD amount TO account-balance GOBACK. END METHOD deposit. END OBJECT. END CLASS Account.
This example shows a simple Account class with instance data (account-balance and account-number) and two instance methods (get-balance and deposit). The CLASS-ID paragraph defines the class name. The OBJECT paragraph contains the instance data and methods that belong to each Account object.
Instance data belongs to each individual object. When you create multiple Account objects, each has its own account-balance and account-number. Factory data (also called static data) is shared by all objects of the class - there's only one copy that everyone shares.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748IDENTIFICATION DIVISION. CLASS-ID. BankAccount AS "BankAccount". DATA DIVISION. WORKING-STORAGE SECTION. FACTORY. DATA DIVISION. WORKING-STORAGE SECTION. 01 total-accounts-created PIC 9(9) VALUE ZERO. *> This is shared by ALL bank accounts PROCEDURE DIVISION. METHOD-ID. new. LINKAGE SECTION. 01 account-number PIC X(10). 01 initial-balance PIC S9(9)V99 COMP-3. 01 self OBJECT REFERENCE BankAccount. PROCEDURE DIVISION USING account-number initial-balance RETURNING self. *> Create new account instance INVOKE SUPER "new" RETURNING self *> Increment shared counter ADD 1 TO total-accounts-created GOBACK. END METHOD new. METHOD-ID. get-total-accounts. PROCEDURE DIVISION RETURNING total AS BINARY-LONG. MOVE total-accounts-created TO total GOBACK. END METHOD get-total-accounts. END FACTORY. OBJECT. DATA DIVISION. WORKING-STORAGE SECTION. 01 my-balance PIC S9(9)V99 COMP-3. 01 my-account-number PIC X(10). *> Each account has its own balance and number PROCEDURE DIVISION. *> Instance methods go here END OBJECT. END CLASS BankAccount.
In this example, total-accounts-created is factory data - all BankAccount objects share this one counter. Each object has its own my-balance and my-account-number (instance data). The factory method "new" is used to create new account instances.
Instance methods operate on a specific object's data. When you call an instance method, it works with that particular object's instance data. Factory methods (static methods) belong to the class itself and don't need an object instance to be called.
123456789101112131415161718192021222324252627282930313233OBJECT. PROCEDURE DIVISION. *> Instance method - operates on THIS object's data METHOD-ID. withdraw. LINKAGE SECTION. 01 amount PIC S9(9)V99 COMP-3. 01 success PIC X. 88 withdrawal-success VALUE 'Y'. 88 withdrawal-failed VALUE 'N'. PROCEDURE DIVISION USING amount RETURNING success. IF my-balance >= amount THEN SUBTRACT amount FROM my-balance SET withdrawal-success TO TRUE ELSE SET withdrawal-failed TO TRUE END-IF GOBACK. END METHOD withdraw. *> Another instance method METHOD-ID. get-account-info. LINKAGE SECTION. 01 info PIC X(50). PROCEDURE DIVISION RETURNING info. STRING "Account: " my-account-number " Balance: " my-balance DELIMITED BY SIZE INTO info GOBACK. END METHOD get-account-info. END OBJECT.
These instance methods work with the specific object's my-balance and my-account-number. Each Account object can call these methods on itself, and they'll operate on that object's own data.
To use objects in COBOL, you need to create them and store references to them. Object references are declared using USAGE IS OBJECT REFERENCE.
12345678910111213141516171819202122232425262728293031323334IDENTIFICATION DIVISION. PROGRAM-ID. AccountTest. DATA DIVISION. WORKING-STORAGE SECTION. 01 account1 OBJECT REFERENCE BankAccount. 01 account2 OBJECT REFERENCE BankAccount. 01 deposit-amount PIC S9(9)V99 COMP-3 VALUE 1000.00. 01 withdraw-amount PIC S9(9)V99 COMP-3 VALUE 250.00. 01 result PIC X. PROCEDURE DIVISION. *> Create first account INVOKE BankAccount "new" USING "ACC001" 500.00 RETURNING account1 *> Create second account INVOKE BankAccount "new" USING "ACC002" 1000.00 RETURNING account2 *> Deposit money into first account INVOKE account1 "deposit" USING deposit-amount *> Withdraw from second account INVOKE account2 "withdraw" USING withdraw-amount RETURNING result IF result = 'Y' THEN DISPLAY "Withdrawal successful" ELSE DISPLAY "Insufficient funds" END-IF STOP RUN.
This program creates two BankAccount objects (account1 and account2), each with different account numbers and initial balances. It then performs operations on each object using the INVOKE statement. Each object maintains its own separate balance.
Inheritance allows a subclass (child class) to inherit methods and data from a superclass (parent class). The subclass can add new methods, add new data, and override inherited methods.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253IDENTIFICATION DIVISION. CLASS-ID. SavingsAccount AS "SavingsAccount" INHERITS BankAccount. DATA DIVISION. WORKING-STORAGE SECTION. OBJECT. DATA DIVISION. WORKING-STORAGE SECTION. 01 interest-rate PIC 9V999 VALUE 0.025. 01 minimum-balance PIC S9(9)V99 COMP-3 VALUE 100.00. PROCEDURE DIVISION. *> Override the withdraw method to check minimum balance METHOD-ID. withdraw. LINKAGE SECTION. 01 amount PIC S9(9)V99 COMP-3. 01 success PIC X. 88 withdrawal-success VALUE 'Y'. 88 withdrawal-failed VALUE 'N'. PROCEDURE DIVISION USING amount RETURNING success. *> Check if withdrawal would violate minimum balance IF (my-balance - amount) >= minimum-balance THEN *> Call parent's withdraw method INVOKE SUPER "withdraw" USING amount RETURNING success ELSE SET withdrawal-failed TO TRUE DISPLAY "Cannot withdraw: would violate minimum balance" END-IF GOBACK. END METHOD withdraw. *> New method specific to savings accounts METHOD-ID. calculate-interest. PROCEDURE DIVISION RETURNING interest AS FLOAT. COMPUTE interest = my-balance * interest-rate GOBACK. END METHOD calculate-interest. *> New method to apply interest METHOD-ID. apply-interest. PROCEDURE DIVISION. COMPUTE my-balance = my-balance + (my-balance * interest-rate) GOBACK. END METHOD apply-interest. END OBJECT. END CLASS SavingsAccount.
SavingsAccount inherits from BankAccount, so it automatically has all of BankAccount's methods and data. It overrides the withdraw method to add a minimum balance check, and adds new methods (calculate-interest and apply-interest) specific to savings accounts. The INVOKE SUPER statement calls the parent class's method.
Encapsulation means that instance data is private and can only be accessed through methods. This protects the data and allows you to control how it's accessed and modified.
1234567891011121314151617181920212223242526272829303132333435363738OBJECT. DATA DIVISION. WORKING-STORAGE SECTION. *> Private instance data - cannot be accessed directly 01 account-balance PIC S9(9)V99 COMP-3. 01 account-number PIC X(10). PROCEDURE DIVISION. *> Getter method - provides read access METHOD-ID. get-balance. PROCEDURE DIVISION RETURNING balance AS FLOAT. MOVE account-balance TO balance GOBACK. END METHOD get-balance. *> Getter method for account number METHOD-ID. get-account-number. PROCEDURE DIVISION RETURNING acct-num AS PIC X(10). MOVE account-number TO acct-num GOBACK. END METHOD get-account-number. *> Setter method - provides controlled write access METHOD-ID. set-balance. LINKAGE SECTION. 01 new-balance PIC S9(9)V99 COMP-3. PROCEDURE DIVISION USING new-balance. *> Can add validation here IF new-balance >= 0 THEN MOVE new-balance TO account-balance ELSE DISPLAY "Error: Balance cannot be negative" END-IF GOBACK. END METHOD set-balance. END OBJECT.
The account-balance and account-number are private - they can't be accessed directly from outside the class. Instead, you must use the getter methods (get-balance, get-account-number) to read them and the setter method (set-balance) to modify them. The setter method can include validation logic to ensure data integrity.
Method overloading allows you to define multiple methods with the same name but different parameter lists. The compiler determines which method to call based on the arguments provided.
12345678910111213141516171819202122232425262728293031323334OBJECT. PROCEDURE DIVISION. *> First version - takes integer amount METHOD-ID. deposit. LINKAGE SECTION. 01 amount-int PIC S9(9). PROCEDURE DIVISION USING amount-int. COMPUTE account-balance = account-balance + amount-int GOBACK. END METHOD deposit. *> Second version - takes decimal amount METHOD-ID. deposit. LINKAGE SECTION. 01 amount-decimal PIC S9(9)V99 COMP-3. PROCEDURE DIVISION USING amount-decimal. ADD amount-decimal TO account-balance GOBACK. END METHOD deposit. *> Third version - takes amount and description METHOD-ID. deposit. LINKAGE SECTION. 01 amount PIC S9(9)V99 COMP-3. 01 description PIC X(50). PROCEDURE DIVISION USING amount description. ADD amount TO account-balance *> Could log the transaction with description DISPLAY "Deposit: " description " Amount: " amount GOBACK. END METHOD deposit. END OBJECT.
All three methods are named "deposit" but have different parameter lists. When you call deposit, the compiler chooses the appropriate version based on what arguments you pass. This provides flexibility and a clean interface.
One of the powerful features of COBOL object-oriented programming is its ability to interact with Java classes. This enables COBOL applications to use Java libraries and allows Java applications to use COBOL classes.
COBOL can create instances of Java classes and invoke Java methods. You declare Java classes in the REPOSITORY paragraph.
12345678910111213141516171819202122232425262728293031323334353637IDENTIFICATION DIVISION. CLASS-ID. CobolJavaBridge AS "CobolJavaBridge". ENVIRONMENT DIVISION. CONFIGURATION SECTION. REPOSITORY. CLASS java-lang-Object CLASS java-util-Date AS "java.util.Date" CLASS java-lang-String AS "java.lang.String". DATA DIVISION. WORKING-STORAGE SECTION. OBJECT. DATA DIVISION. WORKING-STORAGE SECTION. 01 java-date OBJECT REFERENCE java-util-Date. 01 date-string OBJECT REFERENCE java-lang-String. PROCEDURE DIVISION. METHOD-ID. get-current-date-string. PROCEDURE DIVISION RETURNING date-str AS OBJECT REFERENCE. *> Create a Java Date object INVOKE java-util-Date "new" RETURNING java-date *> Call toString() method on the Date object INVOKE java-date "toString" RETURNING date-string *> Return the string MOVE date-string TO date-str GOBACK. END METHOD get-current-date-string. END OBJECT. END CLASS CobolJavaBridge.
This example shows how to use Java's Date class from COBOL. The REPOSITORY paragraph declares the Java classes, and you can then create instances and call methods just like COBOL classes.
A common use case is creating wrapper classes that make existing procedural COBOL code accessible from Java applications.
1234567891011121314151617181920212223IDENTIFICATION DIVISION. CLASS-ID. LegacyCobolWrapper AS "LegacyCobolWrapper". DATA DIVISION. WORKING-STORAGE SECTION. FACTORY. PROCEDURE DIVISION. METHOD-ID. call-legacy-program. LINKAGE SECTION. 01 input-data PIC X(100). 01 output-data PIC X(100). PROCEDURE DIVISION USING input-data RETURNING output-data. *> Call existing procedural COBOL program CALL "LEGACY-PROG" USING input-data output-data GOBACK. END METHOD call-legacy-program. END FACTORY. END CLASS LegacyCobolWrapper.
This factory method wraps a call to an existing procedural COBOL program, making it accessible from Java. Java code can now invoke this method to use the legacy COBOL functionality.
Here's a complete example showing a bank account system with inheritance, encapsulation, and method usage.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697IDENTIFICATION DIVISION. CLASS-ID. Account AS "Account". ENVIRONMENT DIVISION. CONFIGURATION SECTION. REPOSITORY. CLASS java-lang-Object. DATA DIVISION. WORKING-STORAGE SECTION. FACTORY. DATA DIVISION. WORKING-STORAGE SECTION. 01 account-counter PIC 9(9) VALUE ZERO. PROCEDURE DIVISION. METHOD-ID. new. LINKAGE SECTION. 01 acct-num PIC X(10). 01 initial-bal PIC S9(9)V99 COMP-3. 01 self OBJECT REFERENCE Account. PROCEDURE DIVISION USING acct-num initial-bal RETURNING self. INVOKE SUPER "new" RETURNING self ADD 1 TO account-counter INVOKE self "initialize" USING acct-num initial-bal GOBACK. END METHOD new. METHOD-ID. get-account-count. PROCEDURE DIVISION RETURNING count AS BINARY-LONG. MOVE account-counter TO count GOBACK. END METHOD get-account-count. END FACTORY. OBJECT. DATA DIVISION. WORKING-STORAGE SECTION. 01 account-number PIC X(10). 01 balance PIC S9(9)V99 COMP-3. PROCEDURE DIVISION. METHOD-ID. initialize. LINKAGE SECTION. 01 acct-num PIC X(10). 01 initial-bal PIC S9(9)V99 COMP-3. PROCEDURE DIVISION USING acct-num initial-bal. MOVE acct-num TO account-number MOVE initial-bal TO balance GOBACK. END METHOD initialize. METHOD-ID. get-balance. PROCEDURE DIVISION RETURNING bal AS FLOAT. MOVE balance TO bal GOBACK. END METHOD get-balance. METHOD-ID. get-account-number. PROCEDURE DIVISION RETURNING acct-num AS PIC X(10). MOVE account-number TO acct-num GOBACK. END METHOD get-account-number. METHOD-ID. deposit. LINKAGE SECTION. 01 amount PIC S9(9)V99 COMP-3. PROCEDURE DIVISION USING amount. ADD amount TO balance GOBACK. END METHOD deposit. METHOD-ID. withdraw. LINKAGE SECTION. 01 amount PIC S9(9)V99 COMP-3. 01 success PIC X. 88 withdrawal-ok VALUE 'Y'. 88 withdrawal-fail VALUE 'N'. PROCEDURE DIVISION USING amount RETURNING success. IF balance >= amount THEN SUBTRACT amount FROM balance SET withdrawal-ok TO TRUE ELSE SET withdrawal-fail TO TRUE END-IF GOBACK. END METHOD withdraw. END OBJECT. END CLASS Account.
This Account class demonstrates factory data (account-counter), instance data (account-number, balance), factory methods (new, get-account-count), and instance methods (initialize, get-balance, get-account-number, deposit, withdraw). The factory method "new" is used to create new account instances.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152IDENTIFICATION DIVISION. PROGRAM-ID. AccountDemo. DATA DIVISION. WORKING-STORAGE SECTION. 01 my-account OBJECT REFERENCE Account. 01 account-num PIC X(10) VALUE "ACC-001". 01 initial-balance PIC S9(9)V99 COMP-3 VALUE 1000.00. 01 deposit-amt PIC S9(9)V99 COMP-3 VALUE 500.00. 01 withdraw-amt PIC S9(9)V99 COMP-3 VALUE 200.00. 01 current-balance FLOAT. 01 withdraw-result PIC X. 01 total-accounts BINARY-LONG. PROCEDURE DIVISION. *> Create a new account DISPLAY "Creating account..." INVOKE Account "new" USING account-num initial-balance RETURNING my-account *> Get initial balance INVOKE my-account "get-balance" RETURNING current-balance DISPLAY "Initial balance: " current-balance *> Make a deposit DISPLAY "Depositing " deposit-amt INVOKE my-account "deposit" USING deposit-amt *> Get updated balance INVOKE my-account "get-balance" RETURNING current-balance DISPLAY "Balance after deposit: " current-balance *> Make a withdrawal DISPLAY "Withdrawing " withdraw-amt INVOKE my-account "withdraw" USING withdraw-amt RETURNING withdraw-result IF withdraw-result = 'Y' THEN DISPLAY "Withdrawal successful" ELSE DISPLAY "Withdrawal failed - insufficient funds" END-IF *> Get final balance INVOKE my-account "get-balance" RETURNING current-balance DISPLAY "Final balance: " current-balance *> Get total accounts created INVOKE Account "get-account-count" RETURNING total-accounts DISPLAY "Total accounts created: " total-accounts STOP RUN.
This program demonstrates how to use the Account class: creating instances, calling instance methods, and calling factory methods. Each operation works with the specific object's data.
Create a Person class with the following:
Hint: Use STRING to concatenate names. Validate that age is between 0 and 150, and that email contains an "@" symbol.
Create a Student class that inherits from Person and adds:
Hint: Use EVALUATE for letter grade calculation. Use INVOKE SUPER to call parent's full-name method.
Create a Book class and a Library class:
Hint: Use OCCURS clause for the book collection. Use SEARCH to find books by ISBN.
1. What is a class in COBOL object-oriented programming?
2. What is the difference between instance methods and factory methods in COBOL?
3. What keyword is used to define a COBOL class?
4. How do you create an instance of a COBOL class?
5. What is inheritance in COBOL object-oriented programming?
6. What is method overriding in COBOL?
7. What is encapsulation in COBOL object-oriented programming?
8. Can COBOL classes interact with Java classes?
Learn about defining classes, creating objects, and working with object references in COBOL.
Understand how to create subclasses, override methods, and use inheritance hierarchies in COBOL.
Learn how to protect instance data and control access through getter and setter methods.
Understand how to override inherited methods and use the SUPER keyword to call parent methods.
Learn about polymorphism, method overloading, and dynamic method dispatch in COBOL.
Best practices for designing classes, organizing code, and creating maintainable object-oriented COBOL applications.