Thank you for the comments; they got me on the right track. Problem with many sources is they show very simple example where events bring no benefit. It is same as using OOP for a few lines of code, or recursion instead of simple cycle. Such easy example is good to learn the syntax, but it is insufficient to understand the purpose or benefits.
Using events and handlers in one class doesn’t make much sense for me. Most of examples come with two classes (still putting together things that can be alone). For me, an example with three separate pieces of code brought the biggest benefit. According to my understanding, the key points are:
- Class A has an event defined by command
EVENTS
. Class A needs no reference to other classes. In my words: Some situation interesting for the others can happen inside. The class has no knowledge of the outside world (no dependency), but it can signal to the world that the situation happened.
- Only the object A can raise (fire, trigger) the event from its inside code by command
RAISE EVENT
. In my words: It is broadcasted outside (to anyone who could concern and subscribes) that the situation happened.
- Class B defines method/handler for the class A by command
METHODS - FOR EVENT – OF
that CAN be used to handle the event. This class needs to know class A and its event. In my words: Class B offers code to handle situation that can occur in class A.
- Some third piece of code having knowledge of both classes (probably creating them) says: when the event in class A raises use this handler by command
SET HANDLER - FOR
. Most importantly, it can be also another handler from different class than B. In my words: When using class A, I can easily set what will happen after the situation in A by selecting from a range of suitable handlers that A doesn’t know.
Because I miss a good example, here is a demonstration of the points:
CLASS lcl_class_a DEFINITION.
PUBLIC SECTION.
DATA a1 TYPE I.
EVENTS: my_event.
METHODS: method_raising_event.
ENDCLASS.
CLASS lcl_class_a IMPLEMENTATION.
METHOD method_raising_event.
"some working code would be here
RAISE EVENT my_event.
ENDMETHOD.
ENDCLASS.
CLASS lcl_class_b DEFINITION.
PUBLIC SECTION.
"This methods could be run after the event.
METHODS: handle_event1 FOR EVENT my_event OF lcl_class_a,
handle_event2 FOR EVENT my_event OF lcl_class_a.
ENDCLASS.
CLASS lcl_class_b IMPLEMENTATION.
METHOD handle_event1.
WRITE: / 'Event in class raised'.
ENDMETHOD.
METHOD handle_event2.
" Some code, e.g. logging to a file.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA(object_a) = new lcl_class_a( ).
DATA(object_b) = new lcl_class_b( ).
"Binding event and handler.
SET HANDLER object_b->handle_event1 FOR object_a.
CALL METHOD object_a->method_raising_event.
Additions:
- In real life scenarios, it is useful to have reference to object of class A (raiser) in the object of class B (handler). You may need to get an additional information about the event from class A. But it is not necessary.
- More handlers can be attached to one event.
The purpose or benefits are much clearer when aware of some design patterns. Some were mentioned in benefits. I would go with this hierarchy from general to particular:
- SOLID
- Loose coupling / Decoupling / Separation of concerns
- Dependency inversion principle
- Observer – Observable / Subscriber – Publisher
Happy to read comments on my answer.