Доступ к PRIVATE и PROTECTED атрибутам произвольного класса
Как это сделать? С примерами кода.
Некоторое время назад я обнаружил системную функцию SYSTEM-CALL OBJMGR, предназначенную для работы с объектами. Интерес вызывал вариант вызова функции для сохранения состояния объектов SYSTEM-CALL OBJMGR GET STATE. В документации сказано следующее:
Copies the state (of all instance attributes) from object f1 to a dynamically created data structure and returns a data reference f2 (TYPE REF TO DATA) to that structure. You can use this call to save the current state of an object. The variant SET STATE then allows you to reassign the state saved to the object (the object state is reset to its saved state). These calls should only be used by Object Services.
То есть, вызвав данную функцию, можно получить копию всех атрибутов, упакованных в специальную сгенерированную структуру. А если вызвать SYSTEM-CALL OBJMGR SET STATE, то данные из этой структуры переместятся в указанный объект.
Данную функцию SAP использует в классе CL_OS_STATE, предназначенном для манипуляций с состоянием объекта. Приведенные варианты вызовов функций обернуты в методы SET_STATE_FROM_OBJECT и SET_OBJECT_FROM_STATE. Указанные методы в связке реализуют паттерн «Снимок», он же «Хранитель» или «Memento». Паттерн позволяет сохранять состояние класса и восстанавливать его, когда это будет необходимо.
Ниже пример использования данного класса.
CLASS lcl_example DEFINITION. PUBLIC SECTION. METHODS constructor IMPORTING iv_value TYPE i. METHODS print. PRIVATE SECTION. DATA mv_value TYPE i. ENDCLASS. CLASS lcl_example IMPLEMENTATION. METHOD constructor. mv_value = iv_value. ENDMETHOD. METHOD print. WRITE / |Value = { mv_value }|. ENDMETHOD. ENDCLASS. START-OF-SELECTION. DATA lo_foo TYPE REF TO lcl_example. DATA lo_bar TYPE REF TO lcl_example. DATA lo_memento TYPE REF TO cl_os_state. lo_foo = NEW #( 100 ). lo_bar = NEW #( 200 ). lo_memento = NEW #( ). lo_memento->set_state_from_object( lo_foo ). lo_memento->set_object_from_state( lo_bar ). lo_bar->print( ). " WRITE: Value = 100
Зная внутренности структуры данных и имея доступ к ней, можно получить копию атрибутов произвольного объекта. Изменив структуру и восстановив снимок в объект, мы изменим атрибуты объекта.
Иными словами, получив доступ к структуре снимка, мы получим доступ на чтение и на запись к атрибутам класса.
Структура данных «Снимка»
Структура данных снимка находится в атрибуте CL_OS_STATE->STATE. Данный атрибут имеет публичную зону видимости, то есть доступ к нему открыт вне класса.
Ссылка на STATE имеет 2 вложенные структуры: в первой перечислены PROTECTED- и PRIVATE-поля, во второй – PUBLIC-поля. Порядок полей соответствует порядку определения их в классе. Если класс наследуется от другого класса, то сначала перечисляются атрибуты родительских классов, затем дочерних.
Теперь, зная структуру STATE, можно сделать пример, демонстрирующий чтение и запись PRIVATE-атрибутов
CLASS lcl_example DEFINITION. PUBLIC SECTION. METHODS constructor IMPORTING iv_bar TYPE i iv_foo TYPE string. METHODS print. PRIVATE SECTION. DATA mv_bar TYPE i. DATA mv_foo TYPE string. ENDCLASS. CLASS lcl_example IMPLEMENTATION. METHOD constructor. mv_bar = iv_bar. mv_foo = iv_foo. ENDMETHOD. METHOD print. WRITE / |bar={ mv_bar }; foo={ mv_foo }|. ENDMETHOD. ENDCLASS. START-OF-SELECTION. TYPES: BEGIN OF lts_state, bar TYPE i, foo TYPE string, END OF lts_state. FIELD-SYMBOLS <ls_state> TYPE lts_state. DATA lo_object TYPE REF TO lcl_example. DATA lo_memento TYPE REF TO cl_os_state. lo_object = NEW #( iv_bar = 100 iv_foo = 'Im private' ). lo_object->print( ). " bar=100; foo=Im private lo_memento = NEW #( ). lo_memento->set_state_from_object( lo_object ). ASSIGN lo_memento->state->* TO <ls_state> CASTING. <ls_state>-bar = 99. <ls_state>-foo = 'Im public'. lo_memento->set_object_from_state( lo_object ). lo_object->print( ). " bar=99; foo=Im public
Если хотите прочитать статью полностью и оставить свои комментарии присоединяйтесь к sapland
ЗарегистрироватьсяУ вас уже есть учетная запись?
Войти