ABAP OO - Visibility, Availability, Data flow
How do you access the class data in ABAP OO and where is your data currently being processed? There is an example in this article.
Table of contents
This article is about the basics that you should know as a developer if you have been developing software for a long time. However, for a beginner or newcomer to the ABAP programming language it can still be quite difficult to understand. This is where we want to help you.
Introduction
In object-oriented development, it is crucial to choose the right design of the class and variables. A variable has different scopes and can be used in different situations. A global variable does not always have to be used to achieve the right result. In the following sections we will look at the use of different variables and their flow through our logic.
Structure
The scenario is now expanded as follows. We have an interface (ZIF_BS_DEMO_FLOW_CLASS) which provides methods and data and which we use in our class.
INTERFACE zif_bs_demo_flow_class
PUBLIC.
TYPES:
BEGIN OF ts_data,
indicator TYPE i,
text TYPE string,
worked TYPE abap_boolean,
END OF ts_data,
tt_data TYPE STANDARD TABLE OF ts_data WITH EMPTY KEY.
DATA md_interface_content TYPE string.
METHODS get_magic_number
RETURNING VALUE(rd_result) TYPE i.
METHODS get_data
RETURNING VALUE(rs_result) TYPE ts_data.
ENDINTERFACE.
The class ZCL_BS_DEMO_FLOW_CLASS implements the interface so that we can implement the individual methods and have a basis for deployment.
CLASS zcl_bs_demo_flow_class DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES zif_bs_demo_flow_class.
ALIASES: md_interface_content for zif_bs_demo_flow_class~md_interface_content.
CLASS-DATA gd_initialized TYPE abap_boolean.
CLASS-METHODS class_constructor.
METHODS constructor
IMPORTING id_content TYPE string.
PRIVATE SECTION.
DATA md_magic_number TYPE i.
DATA mt_data TYPE zif_bs_demo_flow_class=>tt_data.
ENDCLASS.
CLASS zcl_bs_demo_flow_class IMPLEMENTATION.
METHOD class_constructor.
gd_initialized = abap_true.
ENDMETHOD.
METHOD constructor.
md_interface_content = id_content.
md_magic_number = NEW zcl_bs_demo_random( id_min = 1
id_max = 3 )->rand( ).
mt_data = VALUE #( ( indicator = 1 text = `Line 1` )
( indicator = 2 text = `Line 2` worked = abap_true )
( indicator = 3 text = `Line 3` ) ).
mt_data[ md_magic_number ]-text =
zif_bs_demo_flow_class~md_interface_content.
ENDMETHOD.
METHOD zif_bs_demo_flow_class~get_magic_number.
rd_result = md_magic_number.
ENDMETHOD.
METHOD zif_bs_demo_flow_class~get_data.
DATA(ls_data) = mt_data[ md_magic_number ].
ls_data-worked = abap_true.
rs_result = ls_data.
ENDMETHOD.
ENDCLASS.
To execute the logic, we create the class ZCL_BS_DEMO_FLOW_BASE, which creates objects from our class and calls the individual methods.
CLASS zcl_bs_demo_flow_base DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
ENDCLASS.
CLASS zcl_bs_demo_flow_base IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA(ld_init) = zcl_bs_demo_flow_class=>gd_initialized.
out->write( |Parameter is not initial: { ld_init }| ).
DATA lo_my_flow TYPE REF TO zif_bs_demo_flow_class.
lo_my_flow = NEW zcl_bs_demo_flow_class( `New instance` ).
DATA(lo_my_new) = NEW zcl_bs_demo_flow_class( `New flow` ).
out->write( |Flow magic: { lo_my_flow->get_magic_number( ) }| ).
out->write(
|New magic: { lo_my_new->zif_bs_demo_flow_class~get_magic_number( ) }|
).
out->write( lo_my_flow->get_data( ) ).
out->write( lo_my_new->zif_bs_demo_flow_class~get_data( ) ).
ENDMETHOD.
ENDCLASS.
We will use the entire structure for each example; here you can find the classes compared again.
Visibility
Visibility applies to all content within the section; this can include types, constants, variables or methods. Visibility determines who can access the content.
- PUBLIC - Anyone can access the content.
- PROTECTED - The class itself and the subclasses can access the content.
- PRIVATE - Only the current class can access the content.
Scope
In the first step we look at the scope of variables, where they are visible and how you can use them.
Global
Recognizing global elements in the class you can find the addition CLASS, such as CLASS-DATA or CLASS-METHOD. These elements belong to all instances of the class and are very suitable for buffering data or managing the singleton for the class. The latter is a design pattern in object-oriented development. In this example, we want to access the variable GD_INITIALIZED. The variable was defined without any content and should therefore be empty at the beginning.
To do this, follow these steps:
- First access to the class, this calls the class constructor. This is only called once, on the first access, and not again in the subsequent steps.
- One-time execution of the class constructor, at this point we have access to all methods and data that were defined with CLASS in the class (global, static).
- Set the variable GD_INITIALIZED to ABAP_TRUE, the variable is now filled.
- Since the variable is public, we can access the variable via the class name and assign the contents to our local variable. The value ABAP_TRUE is now also in LD_INIT.
Instance
An instance/member variable is only available to a created instance of a class, regardless of whether it is private or public. Within the instance, the variables are global and are available to every method. However, only data that really needs to be global should be kept here.
To do this, follow the steps below:
- Create a new instance of the class ZCL_BS_DEMO_FLOW_CLASS. If the class constructor has already been run through, the normal constructor will be run through first.
- In the constructor we have access to class methods and attributes, as well as all instance/member variables and normal methods. The constructor is often used to initialize the data within the class. However, you should avoid performing long-running actions in the constructor, such as loading data from the database (lazy loading).
- In the constructor our MD_MAGIC_NUMBER field is already filled with a random number. All methods of the class have access to the variable.
Local
Finally, we look at the local variables; these can only be used within the method where they are defined. After the method has been exited, the variable and its contents are removed from memory.
The following steps are required:
- Read the MT_DATA table and create LS_DATA using an inline declaration.
- Access and modify the data in LS_DATA within the method
- Pass the contents from LS_DATA to RS_RESULT.
Data flow
The most important parameters in development are importing and returning parameters. With Importing we get values and contents into the method and with Returning we return the result.
Importing
In this example we look at what happens to the content from the constructor that we pass to the class. We also look at some special concepts in ABAP.
The following steps:
- Pass the string literal to the constructor of the class. Since we only have one Importing parameter, we can omit the assignment.
- We can access the content via ID_CONTENT within the method. We assign the content to the member variable MD_INTERFACE_CONTENT.
- The assignment is only possible without an interface because we have defined an ALIAS that refers to the variable in the interface.
- The variable that we define in the interface is also available in the class and can be used even if we have not explicitly defined it again.
- Alternatively, we can still access the variable via the interface. In this case, we transfer the content to the table row of the random position.
Returning
Each method can only have exactly one returning parameter. You should therefore decide whether to use exporting, changing or returning when designing the method; a mixture is not necessarily ideal. A returning parameter does not have to be specified, but the call to the method returns the returning value as a result.
To do this, follow these steps:
- We call the method GET_DATA, which is defined in the interface and implemented in the class.
- We access the two members MT_DATA and MD_MAGIC_NUMBER, which are available to the method.
- We define a local variable for the row and set the column "Worked" to ABAP_TRUE.
- The local variable is assigned to RS_RESULT, our returning parameter of the method. Alternatively, you can also use "RETURN ls_data" if you are in BTP or S/4 HANA 2023. Calling the method returns the result, which we pass directly to the WRITE method.
Conclusion
The goal of the article is to give you an insight into the different areas of the classes and how they interact with each other. You can find more information about good object-oriented design in the Clean ABAP Guide.