Define classes based on other classes
- Last Updated: October 30, 2020
- 3 minute read
- OpenEdge
- Version 12.2
- Documentation
A user-defined class (defined using the CLASS statement)
can extend another class by inheriting it. In ABL, a class can inherit
from at most one other class, which in turn can inherit from another
class. This single inheritance model makes the non-PRIVATE data
members, properties, methods, and events of the super class appear
as if they are part of the class being defined. If a class is marked
as FINAL, it cannot be inherited (used as a super
class for another class). The different classes that make up a class
hierarchy are stored in separate class files, both in their source
code form and their r-code form. However, at both compile time and
run time, all the parts of a class hierarchy are treated as a single
unit, and must all run in the same ABL session. Thus, an object
is an instantiation of a class hierarchy, not simply the class that is
instantiated. This object can also represent (have the class type
of) any class in that hierarchy, and can be referenced as any one
of these classes. For more information on class hierarchies and
inheritance, see Class hierarchies and inheritance.
A class can also be abstract. An abstract class is just like a non-abstract class except for three features:
- It must be defined with the
ABSTRACToption. - It cannot be instantiated, but must be inherited by a derived
class; therefore, it cannot be marked
FINAL. - In addition to being able to implement any other class member or element, it can declare abstract properties, methods, and events, each of which must be implemented by a derived class. The implementing class must be the first derived non-abstract class, unless a derived abstract class has already implemented the abstract member.
An abstract property, method, or event is declared with a prototype that defines only type information for the specified class member. No storage or code implementation is associated with an abstract member declaration. The abstract prototype declaration simply creates the requirement that a class member of the specified type must be implemented in a derived class. Otherwise, you can access and manipulate abstract members (according to their type) in a manner similar to implemented members, because an implementation is guaranteed to exist at run time.
A user-defined class can also implement methods, properties,
and events whose prototypes are declared by an interface (defined
in the INTERFACE statement). An interface is not
a class in itself, but similar to a class, it does represent an
object type (interface type). An interface type specifies the prototypes
of properties, methods, and events for classes to implement, similar
to abstract members of a class type. Thus, an interface does not
specify any method, property, or event implementations itself, but it
only provides a particular set of method, property, or event prototypes
that different classes can implement as required. In fact, it is
a compiler error for a class not to provide an implementation for
every method, property, or event prototype specified in an interface
that it implements. An implementing class can meet this requirement
by inheriting method, property, or event implementations from a
super class, as well as by defining its own method, property, or event
implementations.
Again, although an interface is not a class, it does specify the type of an object. Thus, an object instantiated from a class that implements an interface can be referenced as an instance of that interface type as well as an instance of its class type. If a class implements several interfaces, an object instantiated from that class can also be referenced as an instance of each interface type implemented by that class, including any inherited interface types. However, note that you cannot instantiate an interface the way you can instantiate a non-abstract class. You can only reference a class that you have already instantiated as an instance of an interface type that the class implements.
Note that while similar in application, the key difference between interface members and abstract members is that abstract members define prototypes in an abstract class that must be inherited and implemented by a derived class. So, abstract members participate fully in any class hierarchy where they are defined, and can be referenced at the same points in a class hierarchy as any other member. Interface members can only be referenced through the interface type where they are defined or through a class that implements these interface members.