Try OpenEdge Now
skip to main content
Object-oriented Programming
Programming with Class-based Objects : Instantiating and managing class-based objects : Publishing and subscribing to class events : Specifying handler subscriptions for class events
 
Specifying handler subscriptions for class events
ABL allows you to subscribe an internal procedure or a class-based method as a handler for a given class event, and it also allows you to unsubscribe the handler. The effect of this process is similar to subscribing and unsubscribing internal procedures to named events using the SUBSCRIBE and UNSUBSCRIBE statements. However, instead of using these ABL statements for class events, you invoke the ABL built-in event methods Subscribe( ) and Unsubscribe( ), using a syntax that is more natural for object-oriented programming and that supports strong typing when you subscribe methods as event handlers. This syntax also ensures that the event you are referring to is actually a member of the specified class-based object. The return type for these methods is void; so, you must invoke them as a statement (not in an expression).
This is the ABL syntax to manage class event handler subscriptions:

Syntax

[ publisher : ]event-name : { Subscribe | Unsubscribe }
  ( [subscriber : ]handler-method|
    [subscriber-handle , ]handler-procedure ) [ NO-ERROR ] .
Thus, the Subscribe( ) method subscribes the specified method or internal procedure as a handler for the event specified by event-name, and the Unsubscribe( ) method removes the specified method or internal procedure as a handler for the event specified by event-name.
The specified event (event-name) can be a member of any specified class instance or class type (publisher) that defines and publishes the event. If event-name is a static event, publisher must specify the type name of a class that defines the event. If event-name is an instance event, publisher must be an object reference to a class instance that defines the event. The definition of the event can be abstract or implemented as long as the specified class instance actually contains a DEFINE EVENT statement for event-name. The object reference can be of a class or interface type, as long as the referenced type defines the instance event.
If you do not specify a publisher, you must invoke the event subscription method in an ABL class definition, where event-name identifies an event (instance or static) defined in the current class hierarchy. For example, if the unqualified event-name identifies an instance event in the class hierarchy, you must call the event subscription method from within an instance method of the class.
You can specify a class event handler as a class-based instance or static method, where handler-method is the unquoted method name. This method can be either locally accessible to the current class definition or implemented in a specified class instance or class type (subscriber). You can also specify the handler as an internal procedure, where handler-procedure is a character expression that specifies the procedure name. This procedure can be either locally accessible to the current procedure context or implemented in another external procedure context (subscriber-handle). Note that for an internal procedure, you must specify its name using a character expression instead of an unquoted name as for a method name. Also, the kind of event handler you specify is independent of the kind of event. For example, you can specify an instance method, a static method, or an internal procedure as an event handler for either an instance event or a static event.
When you subscribe an event handler to an event, its name is added to a list of handlers for the specified event. Note that you can subscribe the same event handler to two different events as long as the signatures match. However, you can subscribe any given event handler only once to the same event.
Caution: Before subscribing more than one event handler to an event, you should carefully consider how any parameters for the event are defined and how they are processed by each event handler. For more information, see Publishing class events.
Similarly, unsubscribing an event handler from a class event removes the handler’s subscription from the list of event handlers that are subscribed to the event. When you unsubscribe an event handler, if there is no subscription for it in a given event handler list, no action takes place and no error is raised.
Use of the NO-ERROR option supports standard ABL error handling. For more information on error handling for classes, see Raising and handling error conditions.
For a complete description of each event subscription method, see the reference entry for the Subscribe( ) event method and the Unsubscribe( ) event method in OpenEdge Development: ABL Reference.
For example, the following code fragment from the Main sample class subscribes separate handlers to the public OutputGenerated event, which is published in one of two different, but related classes, depending on the Main constructor used to instantiate the class:
USING acme.myObjs.*.
USING acme.myObjs.Common.*.
USING acme.myObjs.Interfaces.*.

CLASS Main:
  DEFINE PRIVATE VARIABLE cOutFile     AS CHARACTER         NO-UNDO.
  DEFINE PRIVATE VARIABLE rCommonObj   AS CLASS CommonObj   NO-UNDO.
  DEFINE PRIVATE VARIABLE rCustObj     AS CLASS CustObj     NO-UNDO.
  DEFINE PRIVATE VARIABLE rCustObj2    AS CLASS CustObj     NO-UNDO.
  DEFINE PRIVATE VARIABLE rHelperClass AS CLASS HelperClass NO-UNDO.
  DEFINE PRIVATE VARIABLE rIBusObj     AS CLASS IBusObj     NO-UNDO.

  /* First constructor instantiates a Customer object */
  CONSTRUCTOR PUBLIC Main ( ):
    ASSIGN
      /* Create an instance of the HelperClass class */
      rHelperClass = NEW HelperClass ( )

      /* Create an instance of the CustObj class */
      rCustObj     = NEW CustObj ( )
      cOutFile      = "Customers.out".

    /* Subscribe OutputGenerated event handler for CustObj */
    rCustObj:OutputGenerated:Subscribe(OutputGenerated_CustObjHandler).
  END CONSTRUCTOR.

  /* Second constructor takes a character parameter representing an input
     file of email addresses to instantiate a New England Customer object */
  CONSTRUCTOR PUBLIC Main (INPUT EmailFile AS CHARACTER):
    ASSIGN
      /* Create an instance of the HelperClass class */
      rHelperClass = NEW HelperClass( )

      /* Create an instance of the NECustObj class */
      rCustObj     = NEW NECustObj (EmailFile)
      cOutFile      = "NECustomers.out".

    /* Subscribe OutputGenerated event handler for NECustObj */
    rCustObj:OutputGenerated:Subscribe(OutputGenerated_NECustObjHandler).
  END CONSTRUCTOR.

  /* Event handlers for each Customer class instance */
  METHOD PRIVATE VOID OutputGenerated_CustObjHandler
      (pcOutputType AS CHARACTER):
    MESSAGE pcOutputType "for all customers." VIEW-AS ALERT-BOX.
  END METHOD.

  METHOD PRIVATE VOID OutputGenerated_NECustObjHandler
      (pcOutputType AS CHARACTER):
    MESSAGE pcOutputType "for New England customers." VIEW-AS ALERT-BOX.
  END METHOD.
  ...
END CLASS.