This is a repost of an article originally posted to the SAP Community Network.
In the past ABAP Trapdoor blogs, I’ve written about various problems that can occur when actually writing code in ABAP. Today’s issue is more about a structural or design problem. For this example, we’ll use the following class hierarchy:

IMPORTING
Imagine a method that takes an instance of CL_SUPER
to perform an arbitrary operation:
METHODS bar
IMPORTING ir_object TYPE REF TO cl_super.
...
DATA: lr_super TYPE REF TO cl_super,
lr_sub1 TYPE REF TO cl_sub1,
lr_sub2 TYPE REF TO cl_sub2.
...
lr_foo->bar( lr_super ).
lr_foo->bar( lr_sub1 ).
lr_foo->bar( lr_sub2 ).
This is pretty straightforward - when calling this method, we can either pass a variable of TYPE REF TO cl_super
or
any of the subclasses because every instance of CL_SUB1
“is-a” CL_SUPER
. This also holds true for subclasses that
the creator of the original classes does not know about - for instance, any customer implementations that extend the
existing framework.

EXPORTING
For methods that provide EXPORTING
parameters, a slightly different pattern applies:
METHODS bar
EXPORTING er_object TYPE REF TO cl_super.
...
DATA: lr_super TYPE REF TO cl_super,
lr_root TYPE REF TO cl_root,
lr_object TYPE REF TO object.
...
lr_foo->bar( IMPORTING er_object = lr_super ).
lr_foo->bar( IMPORTING er_object = lr_root ).
lr_foo->bar( IMPORTING er_object = lr_object ).
In this case, it’s the static type of the variable that receives the exported object that matters: it may be a TYPE REF TO cl_super
or any of its superclasses.

CHANGING
You might have guessed where this leads - for a CHANGING
parameter, you have to observe the constraints that apply to
IMPORTING
parameters as well as those that apply to EXPORTING
parameters - in other words, you can only use the
exact type that is specified by the method. You cannot use any supertype because that would violate the requirement that
every object passed to the method conforms at least to the structure imposed by CL_SUPER
, and you cannot use a subtype
either because the method is not guaranteed to return anything more specific than a reference to CL_SUPER
.

Unclear on the CHANGE?
Now perhaps I’m sticking my neck out a bit far in this case, but I think that in many cases where CHANGING
parameters
are used for object references, they are actually unnecessary and probably used only because of a misunderstanding. Just
to make it clear - to change the state of an object, you do not need to pass it as CHANGING
parameter. The
opposite applies as well: to make the state of an object immutable to the method you’re passing it to, it is not
sufficient to declare it as IMPORTING
parameter.
Let’s explore this a bit further.
METHODs print
IMPORTING ir_person TYPE REF TO cl_person.
...
METHOD print.
DATA: l_name TYPE string,
lr_nobody TYPE REF TO cl_person.
l_name = ir_person-> get_name( ).
WRITE: / 'Name:', l_name.
* changing the reference itself is prohibited:
CREATE OBJECT lr_nobody
EXPORTING i_name = 'Ann Onymous'.
ir_person = lr_nobody. " <--- SYNTAX ERROR
* but changing the state of the referred object is allowed:
ir_person->set_name( 'John Doe' ).
ENDMETHOD.
The scale of the problem
Out of curiosity, I’ve checked a random system and found over 12.000 parameters of protected and public methods that use
CHANGING
reference parameters - so I started digging deeper. Here is what I found:
