ABAP OO - Method parameters
This article explains the basics of parameters in methods and how they behave with different types.
Table of contents
ABAP OO can be seen in many job advertisements as a standard buzzword when it comes to the requirements for an ABAP developer. But in practice we often find that developers lack the basics to create clean objects. This article is about the basics of method parameters, how you can use them and what you can do with them.
Introduction
The parameters are used to exchange information in your class and are very common in classes. If attributes are used much more frequently in your class, you should think again about whether all information really needs to be in attributes or whether it should be passed from method to method via the parameters.
In our example we will use a class that has a very simple structure. It has an attribute that we can edit using a GETTER and SETTER. Furthermore, the initial value is determined via the constructor:
CLASS zcl_bs_demo_object DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
METHODS constructor
IMPORTING id_field TYPE string.
METHODS get_field
RETURNING VALUE(rd_result) TYPE string.
METHODS set_field
IMPORTING id_field TYPE string.
PRIVATE SECTION.
DATA md_field TYPE string.
ENDCLASS.
CLASS zcl_bs_demo_object IMPLEMENTATION.
METHOD constructor.
md_field = id_field.
ENDMETHOD.
METHOD get_field.
rd_result = md_field.
ENDMETHOD.
METHOD set_field.
md_field = id_field.
ENDMETHOD.
ENDCLASS.
Basic
Different types of parameters are available for a method, which can be defined differently using their keywords:
- IMPORTING - Content is entered into the method via this parameter.
- EXPORTING - Values are returned via this parameter.
- CHANGING - This parameter takes over the function of IMPORTING and EXPORTING, i.e. it gets values into the method, but can also change them and send them back.
- RETURNING - Returns exactly one value/object from the method, of which there can only be one parameter per method.
VALUE or REFERENCE
When you define a parameter, you currently have two options available, one as VALUE transfer. A copy of the variable content is provided:
IMPORTING VALUE(id_value) TYPE string
The other way is as REFERENCE, where, as the name suggests, a reference of the value is passed. There are currently two notations, one with the addition like Value and the second variant without the addition, so the variable is automatically treated as a reference.
" Without addition
IMPORTING id_value TYPE string
" With addition
IMPORTING REFERENCE(id_value) TYPE string
Hint: RETURNING parameters only have the addition VALUE.
Behavior
In this section we want to take a look at the behavior of the parameters in three different scenarios and three different characteristics. We use an elementary data type, a reference and an instance for importing, exporting and changing. We pass the data once as a value and reference and try to change the content. In the last step, we simply call the method but do not make any changes to the content.
If we run the example class once, we will get the following output. You can find the example in the lower section of the article:
At the front you will find the respective category, in the brackets the scenario and behind it the values of the respective types.
- Category
- Values - Elementary data type
- References - Reference to data type
- Object - Instance of an object
- Scenario
- def - Initialized values
- byval - Transfer via VALUE
- byref - Transfer via REFERENCE
- unchg - Unchanged values
- Types
- I - Importing
- E - Exporting
- C - Changing
IMPORTING
Importing parameters enter values and content into the method, but according to the definition they should not be changeable. When passing as an elementary data type (REFERENCE), we also receive an error from the compiler when we want to assign a new value, and we cannot activate the source code.
When passing as VALUE, we can work with the variable in the method and even overwrite the value. But this only applies to the current method, because as soon as we leave it, the transfer has the old value again. We only received a "copy" of the variable.
However, the situation with references (TYPE REF) is completely different, regardless of whether it is an importing parameter or an exporting parameter, if we change the content in the method, our variable outside the method also changes.
EXPORTING
Exporting parameters are intended to return results to the shore. If we work using REFERENCE, we also receive the value of the recording variable in the method if it has already been filled.
If we pass the values via VALUE, then the variables are empty and we work with initial variables.
However, caution is advised when we enter the variables into the method via reference. If we do not overwrite or delete the values, the old value remains in the variable, which can lead to later errors in processing. Here it is worth setting the correct type of transfer or deleting the exporting parameters at the beginning of the method.
CHANGING
The changing parameter is the most flexible in this case and behaves the same in all situations, we get the value from outside into the method, we can change it or leave it as is and return the content to the caller.
Example
Here is the complete example class that we used, this class is an executable class with a MAIN method to start in Eclipse.
CLASS zcl_bs_demo_oo_methods DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PRIVATE SECTION.
TYPES: BEGIN OF ts_value,
import TYPE string,
export TYPE string,
change TYPE string,
END OF ts_value.
TYPES: BEGIN OF ts_reference,
import TYPE REF TO string,
export TYPE REF TO string,
change TYPE REF TO string,
END OF ts_reference.
TYPES: BEGIN OF ts_object,
import TYPE REF TO zcl_bs_demo_object,
export TYPE REF TO zcl_bs_demo_object,
change TYPE REF TO zcl_bs_demo_object,
END OF ts_object.
METHODS by_reference
IMPORTING id_value TYPE string
ir_reference TYPE REF TO string
io_object TYPE REF TO zcl_bs_demo_object
EXPORTING ed_value TYPE string
er_reference TYPE REF TO string
eo_object TYPE REF TO zcl_bs_demo_object
CHANGING cd_value TYPE string
cr_reference TYPE REF TO string
co_object TYPE REF TO zcl_bs_demo_object.
METHODS by_value
IMPORTING VALUE(id_value) TYPE string
VALUE(ir_reference) TYPE REF TO string
VALUE(io_object) TYPE REF TO zcl_bs_demo_object
EXPORTING VALUE(ed_value) TYPE string
VALUE(er_reference) TYPE REF TO string
VALUE(eo_object) TYPE REF TO zcl_bs_demo_object
CHANGING VALUE(cd_value) TYPE string
VALUE(cr_reference) TYPE REF TO string
VALUE(co_object) TYPE REF TO zcl_bs_demo_object.
METHODS unchanged
IMPORTING id_value TYPE string
ir_reference TYPE REF TO string
io_object TYPE REF TO zcl_bs_demo_object
EXPORTING ed_value TYPE string
er_reference TYPE REF TO string
eo_object TYPE REF TO zcl_bs_demo_object
CHANGING cd_value TYPE string
cr_reference TYPE REF TO string
co_object TYPE REF TO zcl_bs_demo_object.
METHODS output
IMPORTING io_out TYPE REF TO if_oo_adt_classrun_out
id_scenario TYPE string
is_value TYPE ts_value
is_reference TYPE ts_reference
is_object TYPE ts_object.
ENDCLASS.
CLASS zcl_bs_demo_oo_methods IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA ls_value TYPE ts_value.
DATA ls_reference TYPE ts_reference.
DATA ls_object TYPE ts_object.
ls_value = VALUE #( import = '1'
export = '1'
change = '1' ).
ls_reference = VALUE #( import = NEW #( '1' )
export = NEW #( '1' )
change = NEW #( '1' ) ).
ls_object = VALUE #( import = NEW #( '1' )
export = NEW #( '1' )
change = NEW #( '1' ) ).
output( io_out = out
id_scenario = 'def'
is_value = ls_value
is_reference = ls_reference
is_object = ls_object ).
by_reference( EXPORTING id_value = ls_value-import
ir_reference = ls_reference-import
io_object = ls_object-import
IMPORTING ed_value = ls_value-export
er_reference = ls_reference-export
eo_object = ls_object-export
CHANGING cd_value = ls_value-change
cr_reference = ls_reference-change
co_object = ls_object-change ).
output( io_out = out
id_scenario = 'byref'
is_value = ls_value
is_reference = ls_reference
is_object = ls_object ).
by_value( EXPORTING id_value = ls_value-import
ir_reference = ls_reference-import
io_object = ls_object-import
IMPORTING ed_value = ls_value-export
er_reference = ls_reference-export
eo_object = ls_object-export
CHANGING cd_value = ls_value-change
cr_reference = ls_reference-change
co_object = ls_object-change ).
output( io_out = out
id_scenario = 'byval'
is_value = ls_value
is_reference = ls_reference
is_object = ls_object ).
unchanged( EXPORTING id_value = ls_value-import
ir_reference = ls_reference-import
io_object = ls_object-import
IMPORTING ed_value = ls_value-export
er_reference = ls_reference-export
eo_object = ls_object-export
CHANGING cd_value = ls_value-change
cr_reference = ls_reference-change
co_object = ls_object-change ).
output( io_out = out
id_scenario = 'unchg'
is_value = ls_value
is_reference = ls_reference
is_object = ls_object ).
ENDMETHOD.
METHOD by_reference.
DATA ld_value TYPE string VALUE `Changed`.
* id_value = ld_value.
ir_reference->* = ld_value.
io_object->set_field( ld_value ).
ed_value = ld_value.
er_reference->* = ld_value.
eo_object->set_field( ld_value ).
cd_value = ld_value.
cr_reference->* = ld_value.
co_object->set_field( ld_value ).
ENDMETHOD.
METHOD by_value.
DATA ld_value TYPE string VALUE `Again`.
id_value = ld_value.
ir_reference->* = ld_value.
io_object->set_field( ld_value ).
ed_value = ld_value.
er_reference = NEW #( ld_value ).
eo_object = NEW #( ld_value ).
cd_value = ld_value.
cr_reference->* = ld_value.
co_object->set_field( ld_value ).
ENDMETHOD.
METHOD unchanged.
ENDMETHOD.
METHOD output.
io_out->write( |Values ({ id_scenario }) ... I: { is_value-import }; E: { is_value-export }; C: { is_value-change }| ).
io_out->write(
|Reference ({ id_scenario }) ... I: { is_reference-import->* }; E: { is_reference-export->* }; C: { is_reference-change->* }| ).
io_out->write(
|Object ({ id_scenario }) ... I: { is_object-import->get_field( ) }; E: { is_object-export->get_field( ) }; C: { is_object-change->get_field( ) }| ).
io_out->write( `-` ).
ENDMETHOD.
ENDCLASS.
Conclusion
The use of the various parameters is standard for every ABAP development, although thanks to Clean ABAP the "best" method should only have one or a few importing and one returning parameters. Such methods are very easy to work with, but they are not always so easy to implement.