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.
 
      
      
      
      
      
      
      
      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.
 
      INHERITS super-interface-name [ , super-interface-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.
 
      
      
      
      
      
      
      
      
      
        
          
        
        
          
            [ { temp-table | dataset } ... ]
            [ method-prototypes ] 
            [ property-prototypes ] 
            [ event-prototypes ] 
            END [ INTERFACE ]. 
           | 
        
      
      
      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.
 
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      Declares one or more property prototypes in the interface. A property prototype declares a property of a class without implementing its GET or SET accessors (that is, without specifying the property’s logic). You must specify a property prototype with a PUBLIC access mode. The property prototype must include either a GET and SET accessor, or a GET accessor, or a SET accessor. Although the property declaration cannot have accessor implementations, the property when implemented in a class may include an accessor implementation.
 
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      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 
Customer and related 
Invoice table data for a single 
Customer record from the 
sports2000 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.
 
      
      
        
          
            | 
               
                1.	
               
             | 
            
              r-ICustObjImpl.cls — Defines the  r-ICustObjImpl class, which retrieves data from the single  Customer and related  Invoice records that contain the highest balance value represented by the  Customer.Balance value. 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.)  
             | 
          
        
       
      
        
          
            | 
               
                2.	
               
             | 
            
              r-ICustObjImpl2.cls — Defines the  r-ICustObjImpl2 class, which also retrieves data from a single  Customer and related  Invoice records. However, this class retrieves data for the  Customer whose related  Invoice records contain the highest  Invoice balance represented by the sum of their  Invoice.Amount values.  
             | 
          
        
       
      
      
      
        
          
        
        
          
            INTERFACE r-ICustObj: 
               
              /* Property prototypes to return basic values for the Customer 
                 identified with the highest balance in the database */ 
              DEFINE PUBLIC PROPERTY HighCustBalance AS DECIMAL NO-UNDO 
                GET. 
                SET. 
              DEFINE PUBLIC PROPERTY HighCustNum AS INTEGER NO-UNDO 
                GET. 
                SET. 
                 
              /* Event prototype to notify about Customers with Invoices */ 
              DEFINE PUBLIC EVENT CustHasInvoices  
                SIGNATURE VOID ( piCustNum AS INTEGER ). 
              
              /* Temp-tables for the ProDataSet parameter */ 
              DEFINE TEMP-TABLE ttCust NO-UNDO LIKE Customer. 
              DEFINE TEMP-TABLE ttInv  NO-UNDO LIKE Invoice. 
              
              /* ProDataSet parameter for passing a single Customer with the highest 
                 balance along with its related Invoices */ 
              DEFINE DATASET dsHighCustData FOR ttCust, ttInv 
                DATA-RELATION FOR ttCust, ttInv  
                  RELATION-FIELDS (ttCust.CustNum, ttInv.CustNum). 
              
              /* Method prototype to get the current high Customer balance data */ 
              METHOD PUBLIC VOID GetHighCustomerData 
                ( OUTPUT DATASET dsHighCustData BIND ). 
              
              /* Method prototype to set (or reset) the current high Customer data */ 
              METHOD PUBLIC VOID SetHighCustomerData ( ). 
              
            END INTERFACE. 
           | 
        
      
      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.
 
      
      
        
          
        
        
          
            CLASS r-ICustObjImpl IMPLEMENTS r-ICustObj: 
               
              /* Public properties to return basic values for a customer with the 
                 highest balance */ 
              DEFINE PUBLIC PROPERTY HighCustBalance AS DECIMAL INITIAL 0.0 NO-UNDO 
                GET. 
                SET. 
              DEFINE PUBLIC PROPERTY HighCustNum AS INTEGER INITIAL ? NO-UNDO 
                GET. 
                SET. 
                 
              /* Public event to notify about Customers with Invoices */ 
              DEFINE PUBLIC EVENT CustHasInvoices  
                SIGNATURE VOID ( piCustNum AS INTEGER ). 
              
              /* Private handle variable for the high customer ProDataSet */ 
              DEFINE PRIVATE VARIABLE hHighCustData AS HANDLE NO-UNDO. 
              
              /* Private temp-tables for the high customer ProDataSet */ 
              DEFINE PRIVATE TEMP-TABLE ttCust NO-UNDO LIKE Customer. 
              DEFINE PRIVATE TEMP-TABLE ttInv  NO-UNDO LIKE Invoice. 
              
              /* Private ProDataSet for a single customer with the highest 
                 balance and its invoices */ 
              DEFINE PRIVATE DATASET dsHighCustData FOR ttCust, ttInv 
                DATA-RELATION FOR ttCust, ttInv  
                  RELATION-FIELDS (ttCust.CustNum, ttInv.CustNum). 
              
              /* Private query and data sources for the ProDataSet */ 
              DEFINE PRIVATE QUERY qCust FOR Customer. 
              DEFINE PRIVATE DATA-SOURCE srcCust FOR QUERY qCust. 
              DEFINE PRIVATE DATA-SOURCE srcInv  FOR Invoice. 
              
              /* Constructor to initialize handles and attach data sources */ 
              CONSTRUCTOR r-ICustObjImpl ( ): 
                 
                hHighCustData = DATASET dsHighCustData:HANDLE. 
                BUFFER ttCust:ATTACH-DATA-SOURCE( DATA-SOURCE srcCust:HANDLE ). 
                BUFFER ttInv:ATTACH-DATA-SOURCE( DATA-SOURCE srcInv:HANDLE ). 
                 
              END CONSTRUCTOR. 
           | 
        
        
          
             /* Public method to get the current high customer data */ 
              METHOD PUBLIC VOID GetHighCustomerData 
                ( OUTPUT DATASET dsHighCustData BIND ): 
                   
              END METHOD. 
              
              /* Public method to set (or reset) the current high customer data */ 
              METHOD PUBLIC VOID SetHighCustomerData ( ): 
                 
                hHighCustData:EMPTY-DATASET( ). 
                FOR EACH Customer: /* Find Customer with highest balance */ 
                  FIND FIRST Invoice WHERE Invoice.CustNum = Customer.CustNum NO-ERROR. 
                  IF AVAILABLE Invoice THEN DO: 
                    IF Customer.Balance > HighCustBalance THEN 
                      ASSIGN  HighCustBalance = Customer.Balance 
                              HighCustNum     = Customer.CustNum. 
                    CustHasInvoices:Publish( Customer.CustNum ). 
                  END. 
                END. 
                QUERY qCust:QUERY-PREPARE("FOR EACH Customer " 
                  + "WHERE Customer.CustNum = " + STRING(HighCustNum) ). 
                hHighCustData:FILL( ). 
                 
              END METHOD. 
               
            END CLASS. 
           | 
        
      
      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.)
 
      
      
      
      
      
        
          
        
        
          
            CLASS r-ICustObjImpl2 IMPLEMENTS r-ICustObj: 
               
              /* Public properties to return basic values for a customer with the 
                 highest balance */ 
              DEFINE PUBLIC PROPERTY HighCustBalance AS DECIMAL INITIAL 0.0 NO-UNDO 
                GET. 
                SET. 
              DEFINE PUBLIC PROPERTY HighCustNum AS INTEGER INITIAL ? NO-UNDO 
                GET. 
                SET. 
                 
              /* Public event to notify about Customers with Invoices */ 
              DEFINE PUBLIC EVENT CustHasInvoices  
                SIGNATURE VOID ( piCustNum AS INTEGER ). 
              
              /* Private handle variable for the high customer ProDataSet */ 
              DEFINE PRIVATE VARIABLE hHighCustData AS HANDLE NO-UNDO. 
              
              /* Private temp-tables for the high customer ProDataSet */ 
              DEFINE PRIVATE TEMP-TABLE ttCust NO-UNDO LIKE Customer. 
              DEFINE PRIVATE TEMP-TABLE ttInv  NO-UNDO LIKE Invoice. 
              
              /* Private ProDataSet for a single customer with the highest 
                 balance and its invoices */ 
              DEFINE PRIVATE DATASET dsHighCustData FOR ttCust, ttInv 
                DATA-RELATION FOR ttCust, ttInv  
                  RELATION-FIELDS (ttCust.CustNum, ttInv.CustNum). 
              
              /* Private query and data sources for the ProDataSet */ 
              DEFINE PRIVATE QUERY qCust FOR Customer. 
              DEFINE PRIVATE DATA-SOURCE srcCust FOR QUERY qCust. 
              DEFINE PRIVATE DATA-SOURCE srcInv  FOR Invoice. 
              
              /* Constructor to initialize handles and attach data sources */ 
              CONSTRUCTOR r-ICustObjImpl2 ( ): 
                 
                hHighCustData = DATASET dsHighCustData:HANDLE. 
                BUFFER ttCust:ATTACH-DATA-SOURCE( DATA-SOURCE srcCust:HANDLE ). 
                BUFFER ttInv:ATTACH-DATA-SOURCE( DATA-SOURCE srcInv:HANDLE ). 
                 
              END CONSTRUCTOR. 
           | 
        
        
          
             /* Public method to get the current high customer data */ 
              METHOD PUBLIC VOID GetHighCustomerData 
                ( OUTPUT DATASET dsHighCustData BIND ): 
                   
              END METHOD. 
              
              /* Public method to set (or reset) the current high customer data */ 
              METHOD PUBLIC VOID SetHighCustomerData ( ): 
              
                DEFINE VARIABLE dBalance AS DECIMAL NO-UNDO. 
              
                hHighCustData:EMPTY-DATASET( ). 
                /* Find Customer with highest total Invoice balance */ 
                FOR EACH Customer: 
                  ASSIGN dBalance = 0.0. 
                  FOR EACH Invoice WHERE Invoice.CustNum = Customer.CustNum: 
                    ASSIGN dBalance = dBalance + Invoice.Amount. 
                  END. 
                  IF dBalance > HighCustBalance THEN 
                    ASSIGN  HighCustBalance = dBalance 
                            HighCustNum     = Customer.CustNum. 
                  IF dBalance > 0.0 THEN 
                    CustHasInvoices:Publish( Customer.CustNum ). 
                END. 
                QUERY qCust:QUERY-PREPARE("FOR EACH Customer " 
                  + "WHERE Customer.CustNum = " + STRING(HighCustNum) ). 
                hHighCustData:FILL( ). 
                 
              END METHOD. 
               
            END CLASS. 
           | 
        
      
      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.
 
      
      
      
      
      
        
          
            | 
              
             | 
            
              A class definition (.cls) file can contain only one interface definition that is optionally preceded by one or more USING statements. The complete interface definition must begin with the INTERFACE statement and end with the END statement, and the INTERFACE statement must be the first compileable statement after any USING statements in the file. A class definition file containing an interface definition cannot also contain a class definition.  
             | 
          
        
       
      
      
      
      
      
      
      
      
      
        
          
            | 
              
             | 
            
              While a property interface declaration may include a GET and SET accessor, or a GET accessor, or a SET accessor, 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.  
             |