Like many other garbage-collected programming language, ABAP has its own version of weak references . They are implemented using the class REPORT z_test_weak_ref_buffer.
----
TYPES: t_status_id TYPE c LENGTH 10.
----
CLASS lcl_my_status DEFINITION
----
CLASS lcl_my_status DEFINITION.
PUBLIC SECTION.
DATA status_id TYPE t_status_id.
ENDCLASS. "lcl_my_status DEFINITION
----
TYPES: BEGIN OF t_status_map_entry,
id TYPE t_status_id,
instance TYPE REF TO lcl_my_status,
END OF t_status_map_entry,
tt_status_map TYPE HASHED TABLE OF t_status_map_entry WITH UNIQUE KEY id.
----
CLASS lcl_my_buffer DEFINITION
----
CLASS lcl_my_buffer DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS get_instance
RETURNING value(rr_instance) TYPE REF TO lcl_my_buffer.
METHODS constructor.
METHODS get_status
IMPORTING i_status_id TYPE t_status_id
RETURNING value(rr_status) TYPE REF TO lcl_my_status.
PRIVATE SECTION.
CLASS-DATA sr_instance TYPE REF TO cl_abap_weak_reference.
DATA gt_status_map TYPE tt_status_map.
ENDCLASS. "lcl_my_buffer DEFINITION
----
CLASS lcl_my_buffer IMPLEMENTATION
----
CLASS lcl_my_buffer IMPLEMENTATION.
METHOD get_instance.
IF sr_instance IS INITIAL.
method called for the very first time
CREATE OBJECT rr_instance.
CREATE OBJECT sr_instance
EXPORTING
oref = rr_instance.
ELSE.
try to get the buffered instance using the weak reference
rr_instance ?= sr_instance->get( ).
IF rr_instance IS INITIAL.
the instance was garbage-collected, re-create it
CREATE OBJECT rr_instance.
CREATE OBJECT sr_instance
EXPORTING
oref = rr_instance.
ENDIF.
ENDIF.
ENDMETHOD. "get_instance
METHOD constructor.
DATA: ls_entry TYPE t_status_map_entry.
populate the buffer with some entries
CREATE OBJECT ls_entry-instance.
ls_entry-instance->status_id = 'FOO'.
ls_entry-id = ls_entry-instance->status_id.
INSERT ls_entry INTO TABLE gt_status_map.
CREATE OBJECT ls_entry-instance.
ls_entry-instance->status_id = 'BAR'.
ls_entry-id = ls_entry-instance->status_id.
INSERT ls_entry INTO TABLE gt_status_map.
ENDMETHOD. "constructor
METHOD get_status.
FIELD-SYMBOLS: TYPE t_status_map_entry.
READ TABLE gt_status_map ASSIGNING WITH TABLE KEY id = i_status_id.
rr_status = -instance.
ENDMETHOD. "get_status
ENDCLASS. "lcl_my_buffer IMPLEMENTATION
DATA: gr_buffer TYPE REF TO lcl_my_buffer,
gr_status_foo_1 TYPE REF TO lcl_my_status,
gr_status_foo_2 TYPE REF TO lcl_my_status.
START-OF-SELECTION.
gr_buffer = lcl_my_buffer=>get_instance( ).
gr_status_foo_1 = gr_buffer->get_status( 'FOO' ).
WRITE: / 'Got a status: ', gr_status_foo_1->status_id.
CLEAR gr_buffer.
CALL FUNCTION 'POPUP_TO_CONFIRM'
EXPORTING
text_question = 'Have you tried Control-Alt-Delete?'.
gr_buffer = lcl_my_buffer=>get_instance( ).
gr_status_foo_2 = gr_buffer->get_status( 'FOO' ).
WRITE: / 'Still got the first status: ', gr_status_foo_1->status_id.
WRITE: / 'Got another status: ', gr_status_foo_2->status_id.
IF gr_status_foo_1 = gr_status_foo_2.
WRITE: / 'gr_status_foo_1 = gr_status_foo_2 - fine so far.'.
ELSE.
WRITE: / 'gr_status_foo_1 <> gr_status_foo_2 - malicious developer deception happening right now'.
ENDIF.
You might already have guessed the results:
Got a status: FOO
Still got the first status: FOO
Got another status: FOO
gr_status_foo_1 <> gr_status_foo_2 - malicious developer deception happening right now
In this case, the singleton buffer object was garbage-collected, but the status objects that were supposed to be managed by this singleton were not. The re-created buffer object then provided its own set of status objects - and suddenly, we have different object instances representing the same logical object.
To avoid this kind of situation, there's a simple rule of thumb: A managed object should know its manager. Just make sure that every status object keeps a static reference to the buffer that created it - this will prevent the garbage collection of the buffer as long as one of the status objects is still alive. And always keep in mind that the ABAP garbage collector is rather agressive compared to other programming environments.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
3 | |
3 | |
2 | |
2 | |
2 | |
2 | |
2 | |
1 | |
1 | |
1 |