Find Redefinitions!
In a project I made extensive use of inheritance of a super class. This super class holds all the standard functionality of objects. If a specific object needs to change the standard behaviour the method can be redefined. This concept worked out well.
The problem I faced was, that I didn’t know anymore which sub classes use a special functionality. I had to enter the class, scroll down, find the right method and check if and how the redefinition looked like.
This procedure of course is totally inadequate for a programmer! 😉
So I wrote a little programm which investigates the redfined methods of sub classes.
For example you can enter the class CL_GUI_CONTROL and the method FREE and you will get all subclasses which redefined this method. The classes will be listed in an SALV control.
With a double click on a class the source code of the redefined method will be shown in a docker control.
With this program it’s easy for me to see which of the ~60 sub classes uses a special CALCULATION or extra CHECKs.
Code
Find the code here
REPORT ztrcktrsr_find_redefinitions.
PARAMETERS p_clas TYPE seoclsname DEFAULT 'CL_GUI_CONTROL'.
PARAMETERS p_meth TYPE seocpdname DEFAULT 'FREE'.
CLASS lcl_main DEFINITION.
PUBLIC SECTION.
METHODS on_double_click
FOR EVENT double_click OF cl_salv_events_table
IMPORTING row column.
METHODS docker.
METHODS display.
METHODS do
IMPORTING
i_class TYPE clike
i_method TYPE clike
i_start TYPE boolean_flg.
PROTECTED SECTION.
DATA mt_redef TYPE STANDARD TABLE OF seoredef.
DATA mo_docker TYPE REF TO cl_gui_docking_container.
DATA mo_editor TYPE REF TO cl_gui_abapedit.
METHODS display_source IMPORTING is_source TYPE seoredef.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD on_double_click.
docker( ).
DATA(redef) = mt_redef[ row ].
display_source( redef ).
ENDMETHOD.
METHOD display_source.
DATA lt_source TYPE STANDARD TABLE OF string.
DATA(include) = cl_oo_classname_service=>get_method_include(
EXPORTING mtdkey = VALUE #( clsname = is_source-clsname
cpdname = is_source-mtdname ) ).
READ REPORT include INTO lt_source.
mo_editor->set_text( lt_source ).
ENDMETHOD.
METHOD docker.
CHECK mo_docker IS INITIAL.
mo_docker = NEW #( side = cl_gui_docking_container=>dock_at_right ratio = 50 ).
mo_editor = NEW #( parent = mo_docker ).
mo_editor->set_readonly_mode( 1 ).
ENDMETHOD.
METHOD display.
TRY.
" create SALV
CALL METHOD cl_salv_table=>factory
IMPORTING
r_salv_table = DATA(lr_table)
CHANGING
t_table = mt_redef.
lr_table->get_functions( )->set_all( ).
" register event DOUBLE_CLICK
SET HANDLER on_double_click FOR lr_table->get_event( ).
" hide columns which are not relevant
DATA(lr_columns) = lr_table->get_columns( ).
lr_columns->get_column( 'VERSION' )->set_technical( ).
lr_columns->get_column( 'MTDABSTRCT' )->set_technical( ).
lr_columns->get_column( 'MTDFINAL' )->set_technical( ).
lr_columns->get_column( 'ATTVALUE' )->set_technical( ).
lr_columns->get_column( 'EXPOSURE' )->set_technical( ).
lr_table->display( ).
CATCH cx_salv_error.
ENDTRY.
ENDMETHOD.
METHOD do.
DATA lr_class TYPE REF TO cl_oo_class.
DATA lt_subclasses TYPE seo_relkeys.
DATA ls_subclass LIKE LINE OF lt_subclasses.
TRY .
lr_class ?= cl_oo_class=>get_instance( i_class ).
LOOP AT lr_class->redefinitions INTO DATA(ls_redef) WHERE mtdname = i_method.
APPEND ls_redef TO mt_redef.
ENDLOOP.
lt_subclasses = lr_class->get_subclasses( ).
IF i_start = abap_true.
" search
LOOP AT lt_subclasses INTO ls_subclass.
do( i_class = ls_subclass-clsname
i_method = i_method
i_start = space ).
ENDLOOP.
ENDIF.
CATCH cx_class_not_existent.
ENDTRY.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA(main) = NEW lcl_main( ).
main->do( i_class = p_clas
i_method = p_meth
i_start = abap_true ).
main->display( ).
and on github:Â https://github.com/tricktresor/find_redefinitions
There's actually a very easy way to do this in ADT. In either the class definition or implementation sections, put your cursor on the name of the method you want to check and hit Ctrl+T. This will display a popup window that shows the inheritance tree. If you do this in the highest level superclass, you can quickly see every subclass that implements the method. Classes that redefine the method are shown with a colored icon and black text; classes that do not redefine the method are grayed out. You can select any class to jump immediately to the method implementation in that class.
You can also use Ctrl+T in an interface to see every class that implements the interface method and any subclasses of those classes. Again, any classes where the method is implemented or redefined are shown in color and those that do not are grayed out.
If you're not using ADT yet, I highly recommend it! It takes a little bit of time to get used to it, but once you adjust, there are lots of really great features and improvements over SE80 (especially if you're doing OO development). There are still some limited, specific situations where I need to SE80 (exception classes, primarily), but otherwise, I only use ADT for development now.
Thanks Scott!
Great tip! I will try next time.
Regards
Enno
In SAPGUI, open the object tree. Redefined methods are under their own node.
Great point! I would say that Crtl+T in ADT is better if you're looking for all of the places a specific method is redefined and the the object tree in SE80 is better if you're looking for every method in a particular class that is redefined somewhere. Using Crtl+T on a class name in ADT shows you every subclass, but not the methods that those subclasses redefine.
That's exactly the annoying point:
That means if I have 60 classes I would need to open every single class (+ open redefined methods) to see if there are any. This report shows all of the redefined methods in a list.
Very nice. We need to compile helpful stuff like this into some mega utility some day and release a single abapgit.