1.5 Object-Oriented Programming with COBOL
In the above discussion we have been talking a bit about the philosophy, psychology, and the nature of an object. We will now take a look at what are called the "pillars" of object-oriented programming, that is, encapsulation, inheritance, and polymorphism. These are the core principals of object-oriented programming. COBOL is a newcomer to the world of object-oriented languages (OOLs). C++, Java, Object Pascal, and to some extent Visual Basic 6.0 are but a small sample of the popularity of the object paradigm. Before we dig into the COBOL syntactic details of each pillar at a high level, we will give you an overview of each of the core principals.
1.5.1 Encapsulation Services
The first pillar of OOP is called encapsulation. This is the ability of the language to hide unnecessary implementation details from the object user. For example, if you had created a class named DBWriter (database writer) that has two primary methods, Open() and Close():
NOTE
The database writer encapsulates the details of opening and closing a database.
Identification Division Class-Id Book. <methods and data> Object. <method and data> End Object. End Class Book.
The fictitious DBWriter class has encapsulated the inner details of locating, loading, manipulating, and closing the data file. Notice that this encapsulation pillar of OOP keeps programming tasks simple. The user does not have to worry about the numerous lines of code working behind the scenes to carry out the work of the DBWriter class. The user just has to create an instance and send the appropriate message (e.g., "open the named file"). Closely related to the notion of encapsulating programming logic is the idea of data hiding. An object's state data should ideally be specified as private. The outside world then must ask to change or get the underlying value. Public data points can easily become corrupted, so the private aspect is a good thing.
1.5.2 Inheritance: The "is-a" and "has-a" Relationships
Inheritance is the language's ability to allow you to build class definitions based on existing class definitions. Inheritance therefore allows you to extend the behavior of a base (parent) class by inheriting core functionality into a subclass (also called a child class). Figure 12 shows a simple example. Systems.Object is always the top-most node in any .NET hierarchy. The Shape class extends Object.Shape then defines some number of properties, fields, methods, and events that are common to all shapes. The Circle class extends Shape and inherits the core functionality defined by Shape and Object, as well as defines additional Circle-related details of its own. You then read this diagram as "a circle is-a shape that is-a object." Thus when you have classes related by this form of inheritance, you establish "is-a" relationships between types. The is-a relationship is often termed classical inheritance.
Figure 12 "is-a" Relationship
The other form of code reuse is the containment/delegation model, also known as the "has-a" relationship. A given class can contain another class and expose part or all of its functionality to the user. For example, if you are modeling a truck, you might wish to express the idea that a truck "has-a" heater. It would not be logical to attempt to derive the Truck class from a Heater, or vice versa (a Truck "is-a" heater). You have two independent classes working together where the outer (or containing) class creates and exposes the inner (or contained) class functionality (Figure 13).
Figure 13 "has-a" Relationship
Here the outer object (Truck) is responsible for creating the inner (Heater) object. If the Truck wishes to make the Heater's behavior accessible from a Truck instance, it must extend its own public interface. The object user has no idea that the Truck class is making use of an inner object.
NOTE
The inner Heater is encapsulated by the outer Truck class.
Identification Division Class-Id Truck. <methods and data> Object. <method and data> End Object. End Class Truck.
1.5.3 Polymorphism
The last major pillar of OOP is polymorphism. This is the language's ability to treat related objects the same way. To illustrate polymorphism, let's revisit the shapes hierarchy. Assume that the Shape class has defined a function named Draw(), taking no parameters and returning nothing. Given the fact that every shape needs to render itself in a unique manner, subclasses (such as Circle and Rectangle) are free to reinterpret this method for their own needs (see Figure 14).
Figure 14 Polymorphism
Polymorphism allows a base class to enforce a given behavior on all descendents. From Figure 14, you can assume that any object derived from the Shape class has the ability to be rendered. This is a great capability for any language because you don't need to create redundant methods to perform similar operations (e.g., DrawCircle(), DrawRectangle(), etc.).
Let's wrap up this review of the foundations of OOP. Recall that every object-oriented language needs to address how it contends with encapsulation, polymorphism, and inheritance. The bulk of this chapter will explore the exact COBOL syntax that represents each trait.