Just 4 Versions of the same program to understand OOPs ABAP

We will modify an ABAP program 4 times today and make it an OOPs ABAP program at the 4th Version. Please stay until the end and I promise, you will learn how to program using Object Oriented Approach in ABAP.

I have been programming in ABAP for more than 10 years now but hardly have I designed an end to end development in OOPs ABAP. I have used classes (local/global), methods (static/instance), attributes etc but I cannot claim I am an OOPs ABAP developer. I am still the same old developer who is used to the procedural language. I have worked extensively in Web Dynpro ABAP, which has MVC as the core Architecture and I have followed the principle to the core. But 90 percent of the time I have used the wizard to generate my code in Web Dynpro. Experts suggest we should write those code ourselves. But Lazy ABAPers always use the wizard, after all, why is that magical wand(wizard) provided in the first place.

I understand the concept of OOPs and I do not want to re-iterate the Vehicle examples here. But even though I have not used OOPs extensively, down at the bottom of my heart I know that OOPs if written correctly is better and maintenance is simpler as opposed to the theory of procedural enthusiasts like me who believe OOPs is difficult to maintain.

We always give the excuse that the existing program is not in OOPs so we do not want to introduce OOPs while supporting existing object. The other famous excuse is, the deadline is so aggressive. So let me not venture into OOPs and do the way I know better. With this mind set, I was never able to learn OOPs. But, now I am trying to amend myself. I am trying to write the new developments in OOPs even though it might have flaws. It is never too late to learn. If I look back to the tons of codes which I have written in my initial days using procedural approach, I can point out numerous issues in those so called simple approach. So today, if there is a problem with my OOPs approach, it would just be a learning curve. Tomorrow if I look back to these OOPs programming and I can point out the mistakes, then I should consider I have learned some OOPs then. For some reason, if I am not able to find fault in my OOPs then probably, I never ever programmed in OOPs.

Let me pull a real object from one of my project. We had a report to display all the Roles assigned to any Transaction code which Security Team and Business Team could execute to plan the authorization for different users. Check the program which displays classical report output and internal tables with header line were still the practice then when it was written.

Program Version 1.0

*----------------------------------------------------------------------*
* Author: www.sapspot.com
* Title: Security report - Roles assigned to
* Transaction Codes or vice versa.
*----------------------------------------------------------------------*
* Desc : Generates a report of relationships between Transaction
* Codes and Security Roles. It has options of switching the
* dimensions of the report - i.e. TCODE to ROLE or ROLE to
* TCODE
*----------------------------------------------------------------------*
* Old ABAPer's way of programming
*----------------------------------------------------------------------*
 
SELECTION-SCREEN BEGIN OF BLOCK repopt WITH FRAME TITLE text-001.
PARAMETERS: p_tcode TYPE tcode.
SELECTION-SCREEN END OF BLOCK repopt.
 
* Internal table with Header line
DATA: BEGIN OF t_tcode OCCURS 0,
tcode LIKE agr_1251-low,
ttext LIKE tstct-ttext,
role LIKE agr_1251-agr_name,
rtext LIKE agr_texts-text,
END OF t_tcode.
 
TOP-OF-PAGE.
FORMAT COLOR COL_HEADING.
 
WRITE: / 'Old ABAPer', 60 'Transaction Code to Role Matrix',
136 'Date:', sy-datum.
WRITE: /136 'Page:', (10) sy-pagno NO-SIGN.
ULINE.
WRITE: /(20) 'Txn Code', (36) 'Txn Desc',
60(30)'Role Name', (61) 'Role Desc'.
ULINE.
 
FORMAT COLOR OFF.
START-OF-SELECTION.
 
PERFORM report_by_tcode.
 
*&---------------------------------------------------------------------*
*& Form report_by_tcode
*&---------------------------------------------------------------------*
* Generate report of Roles assigned to TCODEs
*----------------------------------------------------------------------*
FORM report_by_tcode.
SELECT a~low b~ttext a~agr_name c~text INTO TABLE t_tcode
FROM agr_1251 AS a
INNER JOIN tstct AS b ON a~low = b~tcode
INNER JOIN agr_texts AS c ON a~agr_name = c~agr_name
WHERE a~low = p_tcode
AND a~object = 'S_TCODE'
AND b~sprsl = sy-langu
AND c~spras = sy-langu
AND c~line = '00000'
ORDER BY a~low a~agr_name.
 
LOOP AT t_tcode.
* Table name and Header line name is same
WRITE: /(20) t_tcode-tcode, t_tcode-ttext, 60 t_tcode-role, (61) t_tcode-rtext.
ENDLOOP.
ENDFORM. " report_by_tcode

Highlights of the above program which is no more used.

Let us test this program.

Classical Output Report

Now let us check the same program which was written by a programmer who is acquainted with REUSE_ALV_GRID_DISPLAY and who does not declare the internal table with HEADER LINE.

Program Version 2.0

*----------------------------------------------------------------------*
* Relatively New ABAPer's way of programming
*----------------------------------------------------------------------*
 
*----------------------------------------------------------------------*
* TYPE Declaration
*----------------------------------------------------------------------*
TYPES: BEGIN OF ty_tcode,
tcode TYPE agval, " Transaction
ttext TYPE ttext_stct, " Transaction Text
role TYPE agr_name, " Role Name
rtext TYPE agr_title, " Short Description
END OF ty_tcode.
*----------------------------------------------------------------------*
* DATA Declaration
*----------------------------------------------------------------------*
DATA:
gt_tcode TYPE STANDARD TABLE OF ty_tcode,
gs_layout TYPE slis_layout_alv, " Declaration of field
gt_fcat TYPE slis_t_fieldcat_alv, " Declaration of Field
gs_fcat TYPE slis_fieldcat_alv. " Declaration of field
*----------------------------------------------------------------------*
* SELECTION SCREEN
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK repopt WITH FRAME TITLE text-001.
PARAMETERS: p_tcode TYPE tcode.
SELECTION-SCREEN END OF BLOCK repopt.
 
*----------------------------------------------------------------------*
* AT SELECTION-SCREEN.
*----------------------------------------------------------------------*
AT SELECTION-SCREEN.
PERFORM validate_input.
 
*----------------------------------------------------------------------*
* START-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.
 
PERFORM report_by_tcode.
 
*----------------------------------------------------------------------*
* END-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.
 
PERFORM display_report.
 
*----------------------------------------------------------------------*
* SUB ROUTINES
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form VALIDATE_INPUT
*&---------------------------------------------------------------------*
* Validate Selection Input
*----------------------------------------------------------------------*
FORM validate_input.
SELECT COUNT(*) UP TO 1 ROWS
FROM tstc
WHERE tcode = p_tcode.
IF sy-subrc NE 0.
MESSAGE 'Please enter a Valid T-Code' TYPE 'I'.
LEAVE LIST-PROCESSING.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form report_by_tcode
*&---------------------------------------------------------------------*
* Generate report of Roles assigned to TCODEs
*----------------------------------------------------------------------*
FORM report_by_tcode.
SELECT a~low b~ttext a~agr_name c~text INTO TABLE gt_tcode
FROM agr_1251 AS a
INNER JOIN tstct AS b ON a~low = b~tcode
INNER JOIN agr_texts AS c ON a~agr_name = c~agr_name
WHERE a~low = p_tcode
AND a~object = 'S_TCODE'
AND b~sprsl = sy-langu
AND c~spras = sy-langu
AND c~line = '00000'
ORDER BY a~low a~agr_name.
 
ENDFORM. " report_by_tcode
 
*&---------------------------------------------------------------------*
*& Form DISPLAY_REPORT
*&---------------------------------------------------------------------*
* Display Report
*----------------------------------------------------------------------*
FORM display_report .
* Filling field catalog.
PERFORM prepare_fields_description.
* Setting the ALV layout
PERFORM build_layout.
* Display ALV Report
PERFORM display_alv_report.
ENDFORM.
 
*&---------------------------------------------------------------------*
*& Form PREPARE_FIELDS_DESCRIPTION
*&---------------------------------------------------------------------*
FORM prepare_fields_description .
CLEAR gs_fcat.
gs_fcat-fieldname = 'TCODE'.
gs_fcat-seltext_m = 'Txn Code'.
gs_fcat-col_pos = 1.
APPEND gs_fcat TO gt_fcat.
 
CLEAR gs_fcat.
gs_fcat-fieldname = 'TTEXT'.
gs_fcat-seltext_m = 'Txn Desc'.
gs_fcat-col_pos = 2.
APPEND gs_fcat TO gt_fcat.
 
CLEAR gs_fcat.
gs_fcat-fieldname = 'ROLE'.
gs_fcat-seltext_m = 'Role Name'.
gs_fcat-col_pos = 3.
APPEND gs_fcat TO gt_fcat.
 
CLEAR gs_fcat.
gs_fcat-fieldname = 'RTEXT'.
gs_fcat-seltext_m = 'Role Desc'.
gs_fcat-col_pos = 4.
APPEND gs_fcat TO gt_fcat.
 
ENDFORM. " PREPARE_FIELDS_DESCRIPTION
 
*&---------------------------------------------------------------------*
*& Form build_layout
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM build_layout .
gs_layout-no_input = 'X'.
gs_layout-colwidth_optimize = 'X'.
gs_layout-zebra = 'X'.
ENDFORM. " BUILD_LAYOUT
 
*&---------------------------------------------------------------------*
*& Form DISPLAY_ALV_REPORT
*&---------------------------------------------------------------------*
* Display report using ALV grid
*----------------------------------------------------------------------*
FORM display_alv_report.
 
IF gt_tcode[] IS NOT INITIAL.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_buffer_active = space
i_callback_program = sy-repid
is_layout = gs_layout
it_fieldcat = gt_fcat[]
TABLES
t_outtab = gt_tcode
EXCEPTIONS
program_error = 1
OTHERS = 2.
 
ENDIF.
 
ENDFORM. " DISPLAY_ALV_REPORT

Check the output has changed from classical to ALV.

Now, let us check how most of the old-schooled ABAPers try their OOPs programming when they are forced to adopt OOPs. I know some projects where OOPs is the only standard of programming. In such projects, the not so OOPs enthusiast replace PERFORMs by METHODs without really taking the advantage of Object Oriented Architecture. Check how we can really kill the beauty of OOPs below. And I am one of them.

Program Version 3.0

*----------------------------------------------------------------------*
* ABAPer who is trying to write his/her first OOPs development
*----------------------------------------------------------------------*
 
*----------------------------------------------------------------------*
* CLASS-DEFINITIONs and IMPLEMENTATIONs
*----------------------------------------------------------------------*
CLASS lcl_validate_input DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: validate_input.
ENDCLASS.
 
CLASS lcl_validate_input IMPLEMENTATION.
METHOD validate_input.
PERFORM validate_input.
ENDMETHOD.
ENDCLASS.
 
CLASS lcl_fetch_data DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: fetch_data.
ENDCLASS.
 
CLASS lcl_fetch_data IMPLEMENTATION.
METHOD fetch_data.
PERFORM report_by_tcode.
ENDMETHOD.
 
ENDCLASS.
 
CLASS lcl_display_report DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: display_data.
ENDCLASS.
 
CLASS lcl_display_report IMPLEMENTATION.
METHOD display_data.
PERFORM display_report.
ENDMETHOD.
 
ENDCLASS.
 
*----------------------------------------------------------------------*
* TYPE Declaration
*----------------------------------------------------------------------*
TYPES: BEGIN OF ty_tcode,
tcode TYPE agval, " Transaction
ttext TYPE ttext_stct, " Transaction Text
role TYPE agr_name, " Role Name
rtext TYPE agr_title, " Short Description
END OF ty_tcode.
*----------------------------------------------------------------------*
* DATA Declaration
*----------------------------------------------------------------------*
DATA:
gt_tcode TYPE STANDARD TABLE OF ty_tcode,
gs_layout TYPE slis_layout_alv, " Declaration of field
gt_fcat TYPE slis_t_fieldcat_alv, " Declaration of Field
gs_fcat TYPE slis_fieldcat_alv. " Declaration of field
 
* Define the Object Data
DATA:
o_validate TYPE REF TO lcl_validate_input,
o_fetch TYPE REF TO lcl_fetch_data,
o_display TYPE REF TO lcl_display_report.
*----------------------------------------------------------------------*
* SELECTION SCREEN
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK repopt WITH FRAME TITLE text-001.
PARAMETERS: p_tcode TYPE tcode.
SELECTION-SCREEN END OF BLOCK repopt.
 
*---------------------------------------------------------------------*
* INITIALIZATION *
*---------------------------------------------------------------------*
INITIALIZATION.
CREATE OBJECT: o_validate, o_fetch, o_display.
*----------------------------------------------------------------------*
* AT SELECTION-SCREEN.
*----------------------------------------------------------------------*
AT SELECTION-SCREEN.
o_validate->validate_input( ).
 
*----------------------------------------------------------------------*
* START-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.
o_fetch->fetch_data( ).
 
*----------------------------------------------------------------------*
* END-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.
o_display->display_data( ).
 
*----------------------------------------------------------------------*
* SUB ROUTINES
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form VALIDATE_INPUT
*&---------------------------------------------------------------------*
* Validate Selection Input
*----------------------------------------------------------------------*
FORM validate_input.
SELECT COUNT(*) UP TO 1 ROWS
FROM tstc
WHERE tcode = p_tcode.
IF sy-subrc NE 0.
MESSAGE 'Please enter a Valid T-Code' TYPE 'I'.
LEAVE LIST-PROCESSING.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form report_by_tcode
*&---------------------------------------------------------------------*
* Generate report of Roles assigned to TCODEs
*----------------------------------------------------------------------*
FORM report_by_tcode.
SELECT a~low b~ttext a~agr_name c~text INTO TABLE gt_tcode
FROM agr_1251 AS a
INNER JOIN tstct AS b ON a~low = b~tcode
INNER JOIN agr_texts AS c ON a~agr_name = c~agr_name
WHERE a~low = p_tcode
AND a~object = 'S_TCODE'
AND b~sprsl = sy-langu
AND c~spras = sy-langu
AND c~line = '00000'
ORDER BY a~low a~agr_name.
 
ENDFORM. " report_by_tcode
 
*&---------------------------------------------------------------------*
*& Form DISPLAY_REPORT
*&---------------------------------------------------------------------*
* Display Report
*----------------------------------------------------------------------*
FORM display_report .
* Filling field catalog.
PERFORM prepare_fields_description.
* Setting the ALV layout
PERFORM build_layout.
* Display ALV Report
PERFORM display_alv_report.
ENDFORM.
 
*&---------------------------------------------------------------------*
*& Form PREPARE_FIELDS_DESCRIPTION
*&---------------------------------------------------------------------*
FORM prepare_fields_description .
CLEAR gs_fcat.
gs_fcat-fieldname = 'TCODE'.
gs_fcat-seltext_m = 'Txn Code'.
gs_fcat-col_pos = 1.
APPEND gs_fcat TO gt_fcat.
 
CLEAR gs_fcat.
gs_fcat-fieldname = 'TTEXT'.
gs_fcat-seltext_m = 'Txn Desc'.
gs_fcat-col_pos = 2.
APPEND gs_fcat TO gt_fcat.
 
CLEAR gs_fcat.
gs_fcat-fieldname = 'ROLE'.
gs_fcat-seltext_m = 'Role Name'.
gs_fcat-col_pos = 3.
APPEND gs_fcat TO gt_fcat.
 
CLEAR gs_fcat.
gs_fcat-fieldname = 'RTEXT'.
gs_fcat-seltext_m = 'Role Desc'.
gs_fcat-col_pos = 4.
APPEND gs_fcat TO gt_fcat.
 
ENDFORM. " PREPARE_FIELDS_DESCRIPTION
 
*&---------------------------------------------------------------------*
*& Form build_layout
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM build_layout .
gs_layout-no_input = 'X'.
gs_layout-colwidth_optimize = 'X'.
gs_layout-zebra = 'X'.
ENDFORM. " BUILD_LAYOUT
 
*&---------------------------------------------------------------------*
*& Form DISPLAY_ALV_REPORT
*&---------------------------------------------------------------------*
* Display report using ALV grid
*----------------------------------------------------------------------*
FORM display_alv_report.
 
IF gt_tcode[] IS NOT INITIAL.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_buffer_active = space
i_callback_program = sy-repid
is_layout = gs_layout
it_fieldcat = gt_fcat[]
TABLES
t_outtab = gt_tcode
EXCEPTIONS
program_error = 1
OTHERS = 2.
 
ENDIF.
 
ENDFORM. " DISPLAY_ALV_REPORT

Now let us look at the obvious flaws.

Even if you start OOPs programming the above way and you know about the mistakes while writing your second OOPs program, you are on the right path of OOPs. Knowing our own mistake is the first step in learning. The senior mentors and juniors who are expert in OOPs approach should be our guide and pathfinder. Asking for help in understanding the concept should never make us feel ashamed. And no question is too trivial even though you have 10 years of experience. Everyone is learning and it is never too late.

Let us check the better way of writing the same program in OOPs. There might be issues in this code as well, so I humbly request the experts to correct me and show the right way.

I have created three classes in SE24 to simulate the MVC. The selection screen parameters and validation are done in one class. The data retrieval is done in the second class. The report is displayed using the third class. Also, the objects from one class are leveraged in the next class and so on. This program might not show the real arsenal of OOPs but it should be sufficient to showcase what we intend. This is a real program in a real project in a real Client’s SAP system.

Check this OOPs program. Doesn’t it look clean?

Program Version 4.0

*----------------------------------------------------------------------*
* ABAPer who just wrote his first OOPs development nearly correct
*----------------------------------------------------------------------*
 
* Define the Object Data
DATA:
o_selection TYPE REF TO ycl_report_selection,
o_fetch TYPE REF TO ycl_report_fetch,
o_display TYPE REF TO ycl_report_display.
 
*----------------------------------------------------------------------*
* SELECTION SCREEN
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK repopt WITH FRAME TITLE text-001.
PARAMETERS: p_tcode TYPE tcode.
SELECTION-SCREEN END OF BLOCK repopt.
 
*---------------------------------------------------------------------*
* INITIALIZATION *
*---------------------------------------------------------------------*
INITIALIZATION.
CREATE OBJECT o_selection.
CREATE OBJECT o_fetch EXPORTING io_rep_sel = o_selection.
CREATE OBJECT o_display EXPORTING io_rep_fetch = o_fetch.
*----------------------------------------------------------------------*
* AT SELECTION-SCREEN.
*----------------------------------------------------------------------*
AT SELECTION-SCREEN.
* Validation at Selection Screen
o_selection->validate_input( p_tcode ).
 
*----------------------------------------------------------------------*
* START-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.
o_fetch->fetch_data( ).
 
*----------------------------------------------------------------------*
* END-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.
o_display->display_alv( ).

Details of the classes used above in the program.

1. Class: YCL_REPORT_SELECTION

class YCL_REPORT_SELECTION definition
public
final
create public .
 
public section.
 
data G_TCODE type TCODE .
data G_LANGU type SPRAS .
data G_OBJECT type AGOBJECT .
data G_LINE type MENU_NUM_5 .
 
methods VALIDATE_INPUT
importing
!IP_TCODE type TCODE .
protected section.
private section.
 
types:
*----------------------------------------------------------------------*
* TYPE Declaration
*----------------------------------------------------------------------*
BEGIN OF ty_tcode,
tcode TYPE agval, " Transaction
ttext TYPE ttext_stct, " Transaction Text
role TYPE agr_name, " Role Name
rtext TYPE agr_title, " Short Description
END OF ty_tcode .
types:
tt_tcode TYPE STANDARD TABLE OF ty_tcode .
ENDCLASS.
 
CLASS YCL_REPORT_SELECTION IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method YCL_REPORT_SELECTION->VALIDATE_INPUT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IP_TCODE TYPE TCODE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD validate_input.
SELECT COUNT(*) UP TO 1 ROWS
FROM tstc
WHERE tcode = ip_tcode.
IF sy-subrc NE 0.
MESSAGE 'Please enter a Valid T-Code' TYPE 'E'.
ELSE.
* Populate the global variable
g_tcode = ip_tcode.
g_langu = sy-langu.
g_object = 'S_TCODE'.
g_line = '00000'.
ENDIF.
ENDMETHOD.
ENDCLASS.

2. Class YCL_REPORT_FETCH

class YCL_REPORT_FETCH definition
public
final
create public .
 
public section.
 
types:
*----------------------------------------------------------------------*
* TYPE Declaration
*----------------------------------------------------------------------*
BEGIN OF ty_tcode,
tcode TYPE agval, " Transaction
ttext TYPE ttext_stct, " Transaction Text
role TYPE agr_name, " Role Name
rtext TYPE agr_title, " Short Description
END OF ty_tcode .
types:
tt_tcode TYPE STANDARD TABLE OF ty_tcode .
 
data O_REP_SEL type ref to YCL_REPORT_SELECTION .
data T_TCODE type TT_TCODE .
 
methods FETCH_DATA .
methods CONSTRUCTOR
importing
!IO_REP_SEL type ref to YCL_REPORT_SELECTION .
protected section.
private section.
ENDCLASS.
 
CLASS YCL_REPORT_FETCH IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method YCL_REPORT_FETCH->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_REP_SEL TYPE REF TO YCL_REPORT_SELECTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD constructor.
me->o_rep_sel = io_rep_sel.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method YCL_REPORT_FETCH->FETCH_DATA
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD fetch_data.
SELECT a~low b~ttext a~agr_name c~text INTO TABLE t_tcode
FROM agr_1251 AS a
INNER JOIN tstct AS b ON a~low = b~tcode
INNER JOIN agr_texts AS c ON a~agr_name = c~agr_name
WHERE a~low = me->o_rep_sel->g_tcode
AND a~object = me->o_rep_sel->g_object
AND b~sprsl = me->o_rep_sel->g_langu
AND c~spras = me->o_rep_sel->g_langu
AND c~line = me->o_rep_sel->g_line
ORDER BY a~low a~agr_name.
 
ENDMETHOD.
ENDCLASS.

3. Class YCL_REPORT_DISPLAY

class YCL_REPORT_DISPLAY definition
public
final
create public .
 
public section.
 
data O_REP_FET type ref to YCL_REPORT_FETCH .
 
methods DISPLAY_ALV .
methods CONSTRUCTOR
importing
!IO_REP_FETCH type ref to YCL_REPORT_FETCH .
protected section.
private section.
ENDCLASS.
 
CLASS YCL_REPORT_DISPLAY IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method YCL_REPORT_DISPLAY->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_REP_FETCH TYPE REF TO YCL_REPORT_FETCH
* +--------------------------------------------------------------------------------------</SIGNATURE>
method CONSTRUCTOR.
me->o_rep_fet = io_rep_fetch.
 
endmethod.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method YCL_REPORT_DISPLAY->DISPLAY_ALV
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD display_alv.
cl_demo_output=>display_data( EXPORTING
value = me->o_rep_fet->t_tcode
name = 'My First Real OOPs ABAP Development' ).
ENDMETHOD.
ENDCLASS.

The output is the same.

Exercise:

Put breakpoints on the CONSTRUCTOR methods of classes YCL_REPORT_FETCH and YCL_REPORT_DISPLAY and also at the INITIALIZATION of the report. Run your report.

What do you see?

As expected, the CONSTRUCTOR method of the classes would be called at the INITIALIZATION event of the report. Check, how the object data is passed from one class to another in this report and used in other methods (FETCH_DATA and DISPLAY_ALV).

If you want to know the difference between STATIC and INSTANCE method or have fun with CONSTRUCTOR. Read : ABAP Objects Tips