INTERFACE statement
- Last Updated: April 10, 2026
- 10 minute read
- OpenEdge
- Version 13.0
- Documentation
Defines a user-defined interface. An interface defined with this statement represents a user-defined data type that defines a set of method, property, and event prototypes for methods, properties, and events that can be implemented by one or more classes. Any class that implements the interface must support all the methods, properties, and events whose prototypes are defined in the interface or any interface from which this interface inherits member prototypes.
You cannot instantiate an interface as an object. You can only use it to define the specified interface for a class (which you can instantiate) that implements the interface.
.cls) file. For more information, see the Notes section in this reference entry.Syntax
|
- interface-type-name
- Type-name syntax
reference entry. You can also specify an unqualified interface name (without a package),
but only if the interface name represents the full type name for the interface (that is,
the interface is not defined as part of a package).
Note that you cannot specify
"Progress"as the first component of the package name for any ABL user-defined interface. For example,"Progress.Inventory.IUpdateInv"is an invalid type name for a user-defined interface and results in a compiler error. The value of interface-type-name is restricted to alphanumeric characters plus the symbols#,$,%,-, and_. - <type-param AS type-constraint [, type-param AS type-constraint]...>
- Type-param is a type parameter name for a generic type.
Type-param is, by convention, a single uppercase letter. For
instance,
T(for type),K(for Key) andV(for value) are some commonly used type parameter names. - INHERITS super-interface-name [ , super-interface-name ]
- Optionally specifies the type name of one or more other interfaces (super
interfaces) from which this interface inherits member prototypes as
part of its definition. Each
super-interface-nameyou specify can be an ABL or .NET interface type name as described in the Type-name syntax reference entry. With an appropriate USING statement, you can also specify an unqualified interface name (an interface name without the ABL package or .NET namespace that completes the interface type name).Also note that if more than one occurrence of a super interface type or member prototype appears in the interface inheritance hierarchy, it is treated as a single occurrence. However, interface-type-name (the current interface definition type name) can never appear as any super-interface-name, and can never be inherited by any interface specified by a super-interface-name. In other words, there can be no cycles (recursive inheritance) in an interface inheritance hierarchy. Otherwise, ABL raises a compiler error.
- interface-body
-
The body of an interface definition is composed of the following types of elements:
- Temp-table or ProDataSet object definitions used as parameters by one or more methods whose prototype is declared in this interface
- Method prototypes for common methods implemented by one or more classes
- Property prototypes for common properties implemented by one or more classes
- Event prototypes for common events implemented by one or more classes
Define elements in the interface body using the following syntax:
[ { temp-table | dataset } ... ] [ method-prototypes ] [ property-prototypes ] [ event-prototypes ] END [ INTERFACE ].- temp-table | dataset
-
Specifies one or more temp-table or ProDataSet object definitions used as parameters by one or more methods declared in this interface. You must specify these object definitions before any method prototypes. The AVM does not allocate memory for these object definitions. You cannot specify an access mode for these object definitions. These object definitions cannot be inherited from a super interface; they are private to the interface in which they are defined.
The definition of temp-table and ProDataSet object parameters for methods defined in any classes that implement this interface must match the temp-table or ProDataSet object definitions in this interface.
For temp-table objects:
- The temp-tables must have the same number of fields, and each field must match with respect to the data type, extent, and position. Neither the table names nor field names must match.
- The temp-tables must have the same number of indexes, and each index component must match, including the index names. However, the index-component field names do not need to match.
For ProDataSet objects:
- The ProDataSet objects must have the same number of member buffers, and the buffers must be in the same order. Neither the buffer names nor ProDataSet names must match.
- The temp-tables of these buffers must match as described above.
- method-prototypes
-
Declares one or more method prototypes in the interface. A method prototype declares a method of a class without an implementation (that is, without specifying the method's logic or the
END METHODstatement).For information on the syntax for method-prototype, see the METHOD statement reference entry for declaring method prototypes. Note the following:
- The method access mode must be
PUBLIC, either explicitly declared or defaulted. - The method prototype must not include the
STATIC,ABSTRACT, orFINALoptions. - The
OVERRIDEoption can only be specified for methods that are defined inProgress.Lang.Object, however this is not required.
The implementation of these method prototypes, in classes that implement this interface, must not include the
STATICoption and must match these declarations with respect to:- Access mode, which must be
PUBLIC - Return type
- The number, data type, and access mode of any parameters
- The method access mode must be
- property-prototypes
-
Declares one or more property prototypes in the interface. A property prototype declares a property of a class without implementing its
GETorSETaccessors (that is, without specifying the property's logic). You must specify a property prototype with aPUBLICaccess mode. The property prototype must include either aGETandSETaccessor, or aGETaccessor, or aSETaccessor. Although the property declaration cannot have accessor implementations, the property when implemented in a class may include an accessor implementation.For information on the syntax for property-prototype, see the DEFINE PROPERTY statement reference entry for declaring property prototypes. Note the following:
- The property access mode must be
PUBLIC, either explicitly declared or defaulted. - The property prototype must not include the
STATIC,ABSTRACT,OVERRIDE, orINITIALoptions. - Accessors must not include access modifiers.
- Accessors must not include implementations.
The implementation of the property, in classes that implement this interface, must not include the
STATICoption and must match these declarations with respect to:- Access mode, which must be
PUBLIC - Name
- Data type or type name
EXTENT— Its presence or absence, determinate or indeterminate, and size (if determinate)- Accessors — Any accessor appearing in the interface, plus
the option of any additional accessor not specified in the interface, all
defaulting to
PUBLICaccess mode - Presence or absence of
NO-UNDO
- The property access mode must be
- event-prototypes
-
Declares one or more event prototypes in the interface. An event prototype declares a class event that the class must implement with an identical declaration, allowing the class to publish the event.
For information on the syntax for event-prototype, see the DEFINE EVENT statement reference entry for declaring class event prototypes. Note the following:
- The event access mode must be
PUBLIC, either explicitly declared or defaulted. - The event prototype must not include the
STATIC,ABSTRACT, orOVERRIDEoptions.
The implementation of these event prototypes, in classes that implement this interface, must not include the
STATICoption and must match these declarations with respect to:- Access mode, which must be
PUBLIC - Any specified .NET delegate type or the number, data type, and access mode of any specified parameters
- The event access mode must be
- END [ INTERFACE ]
- Specifies the end of the interface body definition. You must
end the interface body definition with the
ENDstatement.
Examples
The following samples include two different class definitions that provide
similar functionality, but in distinctly different ways. Each class implements the same
interface and both classes define a ProDataSet data member (dsHighCustData) used to retrieve Defines the type name for a user-defined
interface type. Specify an ABL interface type name as described in the Customer and related Invoice
table data for a single Customer record from the Sports2020 database. However, each class selects the Customer record using a different and functionally distinct
algorithm provided in its own implementation of the same interface method prototype.
Thus,
each of the following sample class files implements the r-ICustObj interface
type defined in the class definition file, r-ICustObj.cls and
provides the following functionality:
-
r-ICustObjImpl.cls —
Defines the r-ICustObjImpl class, which retrieves
data from the single
Customerand relatedInvoicerecords that contain the highest balance value represented by theCustomer.Balancevalue. This functionality is almost identical to what is provided by the r-CustObj.cls sample class file that is fully described in the Examples section of the CLASS statement reference entry. (The main differences from the r-ICustObjImpl class are that the r-CustObj class does not implement an interface type and it is defined as FINAL.) -
r-ICustObjImpl2.cls — Defines the r-ICustObjImpl2 class,
which also retrieves data from a single
Customerand relatedInvoicerecords. However, this class retrieves data for theCustomerwhose relatedInvoiceDefines the type name for a user-defined interface type. Specify records contain the highestInvoicebalance represented by the sum of theirInvoice.Amountvalues.
Following is the interface definition provided by the sample r-ICustObj.cls file.
r-ICustObj.cls
|
The implementations of the SetHighCustomerData( ) method
populate the ProDataSet with selected fields from Customer and Invoice records,
where the selected Customer also has related invoices.
Each implementation of SetHighCustomerData( ) also
sets the two implemented properties (HighCustBalance and HighCustNum)
to appropriate values for the selected Customer,
and publishes the implemented class event (CustHasInvoices)
for each Customer record it encounters with related Invoice records.
Each class defines additional data members to support its instance
of the ProDataSet, and also must implement the GetHighCustomerData( ) method
(according to the interface) to pass the ProDataSet as a by-reference
output parameter.
Following is the interface implementation
provided by the r-ICustObjImpl sample class. Note
that the property implementations add initial values, but rely on
default behavior for the accessors. The class also fully defines
the ProDataSet to be passed as a by-reference method output parameter.
r-ICustObjImpl.cls
|
The bold code inside the SetHighCustomerData( ) method
shows the difference in implementation from the same method implemented
by the following r-ICustObjImpl2 sample class.
Here, it relies on the stored value of the Customer.Balance field
to determine each Customer balance and assigns
the HighCustBalance and HighCustNum property
values accordingly.
The following r-ICustObjProc.p sample
procedure shows an application of the r-ICustObjImpl class,
which responds to the CustHasInvoices class event
and displays the contents of the dsHighCustCata ProDataSet.
Note that it defines a reference-only instance of the ProDataSet
as required by the class and its interface. (This application is
identical to the r-CustObjProc.p sample procedure
described in the Examples section of the CLASS statement,
but which instantiates the r-CustObj sample class instead.)
r-ICustObjProc.p
|
Following is the interface implementation provided
by the r-ICustObjImpl2 sample class. This implementation is
identical to r-ICustObjImpl except for the SetHighCustomerData( ) method.
r-ICustObjImpl2.cls
|
The bold code inside the SetHighCustomerData( ) method
shows the difference in implementation from the same method implemented
by the previous r-ICustObjImpl sample class. Here,
it calculates the Customer balance from the total
of Invoice.Amount values in its related Invoice records
and assigns the HighCustBalance and HighCustNum property
values accordingly.
The following r-ICustObjProc2.p sample procedure
shows an application of the r-ICustObjImpl2 class,
which is very similar to the previous procedure, r-ICustObjProc.p.
The differences include displaying both the stored Customer.Balance value
and the Invoice.Amount total for the selected Customer record,
as well as some cosmetic changes to the display. Otherwise, the
application is identical.
r-ICustObjProc2.p
|
Notes
- You can terminate an
INTERFACEstatement with either a period (.) or a colon (:), but typically use a colon (:). - A class definition (
.cls) file can contain only one interface definition that is optionally preceded by one or moreUSINGstatements. The complete interface definition must begin with theINTERFACEstatement and end with theENDstatement, and theINTERFACEstatement must be the first compilable statement after anyUSINGstatements in the file. A class definition file containing an interface definition cannot also contain a class definition. - The access mode for an interface definition is always
PUBLIC. - The compiled version of an interface definition file is an r-code (
.r) file. For more information, see the COMPILE statement reference entry. - You can define an object reference variable for an interface, which lets you reference a class that implements the interface, but you cannot create an instance of an interface with the NEW function (classes). For more information on object references, see the AS CLASS option in the DEFINE VARIABLE statement reference entry and see the Class-based object reference reference entry.
- You can reference include files from within an interface definition. For more information about include files, see the { } Include file reference entry.
- All built-in preprocessor directives are supported in interface definitions.
- All built-in preprocessor names are supported in interface definitions. For a list of preprocessor name, see the { } Preprocessor name reference entry.
- You cannot pass compile-time arguments to interface definition files. However, you can pass compile-time arguments to include files referenced in an interface definition file.
- You can store class definition r-code files in ABL libraries (procedure libraries (.pl) or archive files (.apl). If ABL encounters a library on the PROPATH, it will search the library for the specified r-code. However, you cannot execute r-code files stored in a library that is not on the PROPATH using the library-path<<member-name>> syntax.
- While a property interface declaration may include a
GETandSETaccessor, or aGETaccessor, or aSETaccessor, you cannot force the property to NOT have a particular accessor in an implementing class. However, you can force the accessor to be missing when an instance of the class is used through an interface reference. You can do this by omitting the accessor in the property interface definition. Even though the accessor might be implemented in the class property, it will appear, when used through an interface reference, that the accessor implementation does not exist.
See also
Class-based object reference, CLASS statement, DEFINE DATASET statement, DEFINE EVENT statement, DEFINE PROPERTY statement, DEFINE TEMP-TABLE statement, METHOD statement, Type-name syntax, USING statement