Try OpenEdge Now
skip to main content
Object-oriented Programming
Object-oriented Programming and ABL : Overview of object-oriented programming : Inheritance
 

Inheritance

Code reuse is one of the great benefits of object-oriented programming. Procedural programming provides code reuse to a certain degree—you can write a procedure and then use it as many times as you want. However, object-oriented programming goes an important step further by allowing you to define relationships between classes. These relationships facilitate code reuse as well as better overall design, by organizing classes and factoring out common elements of related classes. Inheritance is one means of providing this functionality.
Inheritance allows a given class to inherit data members, properties, methods, and events from another class—that is, it allows a given class to adopt members of another class in such a way that the given class appears to have defined these members within itself. If one class explicitly inherits from another, the inherited class is a super class of the class that inherits from it. Conversely, any class that inherits from a super class is a subclass (also known as a derived class) of the specified super class. The entire series of super classes and the one most derived class that inherits from all of them form a chain of inheritance that represents the class hierarchy of that most derived class. Thus, both a class and any of its super classes can provide data members, properties, methods, and events for the definition of that class.
The following figure shows an example of inheritance, where ClassB is the immediate super class of ClassC, and ClassA is the immediate super class of ClassB. The derived class, ClassC, thus inherits class members from both ClassA and ClassB.
Figure 2. Inheritance example
So, when the pseudo-code fragment in the figure instantiates ClassC, the resulting object (ObjectC) contains all three class definitions according to the specified class hierarchy. ClassA defines protected methods that are inherited and accessible only within the class hierarchy itself, ClassB defines a public method inherited by ClassC, and ClassC also defines a public method. Thus, the object defined as an instance of ClassC effectively provides both public methods for access by the pseudo-code fragment. The numbered arrows show the following characteristics that define ClassC and its hierarchy and how they are accessed by the pseudo-code fragment using the ClassC instance:
1. ClassC’s public method, MethodC( ) calls ClassA’s protected method, MethodA1( ), which sets the private data of MethodC( ), DataC, from the value of DataA. MethodC( ) then passes the new value of DataC as its output parameter.
2. ClassB’s public method, MethodB( ), calls ClassA’s protected method, MethodA2( ) to set DataA from its own private data, DataB, and passes the value of DataB as its output parameter.
3. The pseudo-code fragment calls MethodC( ) on the ClassC instance, ObjectC, returning the value currently set for DataA.
4. The pseudo-code fragment calls MethodB( ) on the ClassC instance, ObjectC, changing the value of DataA and returning that value, which is currently set for DataB.
Again, these classes also encapsulate all of their data, and the class hierarchy provides well managed access to it. So, ClassC’s inheritance as the most derived class allows access to all public and protected methods in the hierarchy, and the protected methods of ClassA allow all of its derived classes to access and modify the value of its private data without providing direct access to the private data itself.
One of the major design goals in object-oriented programming is to factor out common behavior of various classes and separate the common behavior into a super class, which defines behavior for each of its subclasses to implement. This super class contains all the members that are common to the subclasses that inherit from it. This inheritance relationship is defined at compile-time and any modifications to a super class are automatically propagated to each of its subclasses. In other words, inheritance creates a strong, permanent coupling between a super class and its subclasses.
A subclass can also override the behavior of its super class by providing a method with the same signature but different behavior from the super class. The overriding method can access the behavior in the super class method, augmenting the super class behavior with pre- or post-processing. This pre- or post-processing contains the subclass’s own unique behavior for the overriding method.
Note: Method overriding is fundamental to implementing polymorphism. For more information, see Polymorphism.
ABL, like Java and some other object-oriented languages, uses a single-inheritance model. This model allows a subclass to explicitly inherit from only a single super class. This single super class can then inherit from a single super class, and so on. Thus, a subclass explicitly inherits from its single, immediate super class and implicitly inherits from any single-inherited super classes above it in the class hierarchy. The very top of the class hierarchy is the root class, which is the super class that all subclasses implicitly inherit. ABL provides a built-in root class, Progess.Lang.Object (see Using the root class: Progress.Lang.Object). A subclass and its class hierarchy can also implement one or more interface types that the subclass explicitly specifies, including any interfaces that these interface types inherit. However, interfaces cannot inherit member prototypes from a class, nor can they, themselves, be inherited by a class.
* Comparison with procedure-based programming