Override class events within a class hierarchy
- Last Updated: October 30, 2020
- 6 minute read
- OpenEdge
- Version 12.2
- Documentation
It is invalid to have an implemented class event in a subclass with the same
name as any PUBLIC, PACKAGE-PROTECTED, PROTECTED, or PACKAGE-PRIVATE class event in one of its super classes, regardless
of whether the signatures of the two events match. Thus, it is impossible to define an event
in a subclass that might override (shadow) or conflict with an implemented event in a super
class without returning an error from the compiler.
Note that you must override and implement any abstract events in a non-abstract subclass that inherits them. However, if the inheriting subclass is abstract, you can, at your option, override any inherited abstract event and designate it again as abstract. The only difference you can make in creating a new abstract event definition is to specify a less restrictive access mode, overriding a protected abstract event to make it public. Note, again, like an implemented property, that you cannot override an implemented event and make it abstract.
Note also that for abstract events, unlike for abstract properties
or methods, the point at which you provide the non-abstract definition
of the event determines where you can publish the event. However,
you can subscribe a handler for an abstract event at all the same
points in a class hierarchy where you can access an abstract property
or method. Thus, you can subscribe a handler for any accessible
event, whether the event is abstract or implemented at the point in
a class hierarchy where you create the event handler subscription.
However, you can publish an implemented event only within the class
definition that implements it, which is the class that contains
a DEFINE EVENT statement for the event without
the ABSTRACT option. For more information on publishing and
subscribing event handlers for a class event inside and outside
of a class hierarchy, see Publish and subscribe to class events.
The following figure shows how a method override invoked on the defining super class executes within a class hierarchy, using pseudo-code to represent the behavior. The figure shows four classes forming an inheritance hierarchy with ClassA as the root class and ClassD as the most derived subclass. ClassA defines a MethodA( ), which is overridden, in turn, by ClassB, then by ClassC, which is also the most derived subclass that overrides the method.
This pseudo-code fragment defines an object reference (dotted arrow) to the ClassA data type (ObjectA), and according to the numbered arrows:
- Instantiates ClassD, returning its object reference as ObjectD (1a) and executes MethodD( ) on ObjectD (1b). MethodD( ) then invokes MethodA( ) within the class hierarchy of the object. Because the most derived subclass in the object that overrides MethodA( ) is ClassC, ClassC’s definition of this method executes (1c).
- Assigns the ClassA object reference, ObjectA, to reference the ClassD instance (2a) and executes MethodA( ) on ObjectA (2b), which references the object as a ClassA instance and invokes the same MethodA( ) override (ClassC’s) that was previously invoked through the ObjectD reference (1c).

Now, suppose ClassE inherits from the ClassD and also overrides MethodA( ), as shown in the following figure.

In this hierarchy, ClassE is the most derived subclass that overrides the method. So, as shown according to the numbered arrows, this pseudo-code:
- Instantiates ClassE, returning its object reference as ObjectE (1a) and executes the inherited MethodD( ) on ObjectE (1b). MethodD( ) then invokes MethodA( ) within the class hierarchy of the object. Because the most derived subclass that overrides MethodA( ) is now ClassE, ClassE’s definition of that method executes (1c).
- Assigns the ClassA object reference, ObjectA, to reference the ClassE instance (2a) and executes MethodA( ) on ObjectA (2b), which references the object as a ClassA instance and invokes the same MethodA( ) override (ClassE’s) that was previously invoked through the ObjectE reference (1c).
Note that, in general, you cannot invoke overrides of a method other than the override in the most derived subclass. For example, there is no way to directly access the MethodA( ) override defined in ClassB, even from within ClassB, because all direct calls to MethodA( ) anywhere inside or outside the class hierarchy execute the override in ClassE.
However, using the SUPER system reference, ABL allows
any method in a subclass to invoke the behavior of a specified method
in the nearest super class where it is defined. Thus, the MethodA( )
override defined in ClassE can invoke the behavior for the MethodA( )
definition that it overrides in ClassC. Similarly, MethodD( )
can use the SUPER system reference to invoke the
behavior of the MethodA( ) defined in ClassC instead of
invoking the override in the most derived subclass, ClassE. For
more information on the SUPER system reference,
see SUPER system reference.
If the super class's method is defined as PRIVATE,
the method is not inherited by the subclass. If the subclass defines
a method of the same name, it is not overriding the super class
method because the super class's definition is not available to
the subclass. In this case, the subclass method is entirely independent
of the super class method. Because of this, it does not matter whether
the methods match in their return type, access mode, or parameters.
Also in this case, use of the OVERRIDE keyword
on the method is not allowed.
If the super class's non-private method is defined as FINAL,
no subclass can override that method. The compiler returns an error
if you attempt to compile a subclass that has a method with the
same name as a FINAL method in a super class, regardless
if the signatures match.
The following sample class references and extends the sample subclass,
acme.myObjs.CustObj (see Sample classes). This sample extension overrides the GetCustomerName( ) method to return an E-mail address with the customer name:
|
This extension adds a new temp-table to provide the E-mail address, which is initialized by
the constructor for NECustObj. Note that only methods can be overridden,
constructors and destructors are implicitly FINAL and cannot be overridden in
a subclass.
Method overriding supports polymorphism, because it allows you to call a method on a super class object reference, and the method invoked depends on the actual class instance that overrides the super class definition of that method. Thus, you can invoke different behavior using an identical method call, depending on the subclass object referenced by the super class object reference. At compile time, you do not necessarily know the class type of the object whose method override will execute. However, the method override that executes is always the method definition in the most derived class that defines the method in the hierarchy of that class type.
From a practical programming viewpoint, then, method overriding
simplifies the code to execute different behaviors that might otherwise
require long CASE or nested IF statements
to select among them. The new behavior is selected simply by referencing
an instance of a different class that overrides the same method
call. For more information on how to use polymorphism with method
overriding, see Use polymorphism with classes.
You can also define multiple methods with the same name that you invoke with different signatures, a practice known as overloading. Method overloading provides a mechanism that you can use together with polymorphism to identify specific method calls, but you need to know at compile time the particular signature of each overloaded method you want to call in the class hierarchy of the object. For more information on method overloading, see Overload methods and constructors.