Reputation:
I want to write a method which exports a table of references. This is required because each line of it could have its own structure. So I'm declaring the type like this:
... TYPE STANDARD TABLE OF REF TO data.
I thought it would be a neat idea if I could immediately modify the tables last row instead of having a separate workarea just for appending.
Why does this work...
FIELD-SYMBOLS: <lfs_struct> TYPE REF TO DATA.
" ...
APPEND INITIAL LINE TO ei_lines ASSIGNING <lfs_struct>.
CREATE DATA <lfs_struct> TYPE (<lfs_field>-segnam).
ASSIGN <lfs_struct>->* TO <lfs_target>.
...but this doesn't?
DATA: lo_struct TYPE REF TO data.
" ...
APPEND INITIAL LINE TO ei_lines REFERENCE INTO lo_struct.
CREATE DATA lo_struct TYPE (<lfs_field>-segnam).
ASSIGN lo_struct->* TO <lfs_target>.
With 'work' I mean that the value of the appended row really changes. If I assign something to <lfs_target>
like I do in the second example, it changes in the structure itself - but not inside the table.
Apparently I am changing the reference with the last example. But why does it work with Field-Symbols then?
Upvotes: 8
Views: 764
Reputation: 10409
The reason why your code works with a field symbol but not a data object is because of how those two deal with data in memory in a different way. There are similar concepts in C++, even though naming in ABAP is a bit confusing when you are used to C++:
In ABAP a field symbol is a bit like a reference in C++ (or like a dereferenced C++ pointer, as SAP calls it). It does not allocate memory for its own data, but rather refers to some existing field / data object. After assigning a data object to the field symbol, if you access that data object via the field symbol, then you don't ever talk to the field symbol itself, but always to the data object directly! (This is the crucial part in your case, as we see in a bit.)
Now in your first example you create the field symbol, which does nothing yet:
FIELD-SYMBOLS: <lfs_struct> TYPE REF TO DATA.
Only after creating the new line for your internal table and assigning that newly allocated memory to your field symbol <lfs_struct>
, the field symbol points to some data (the table line). Then you allocate some more memory dynamically:
CREATE DATA <lfs_struct> TYPE (<lfs_field>-segnam).
Now your internal table ei_lines
points to the newly appended table line (memory address), as does your field symbol. That memory address in turn points to the newly created data from CREATE DATA
. Important to note is that, as said, you don't access the field symbol itself, but the memory where it refers to!
In the second example however you first allocate memory for a new data object:
DATA: lo_struct TYPE REF TO data.
Then again you allocate new memory for a new table line (APPEND
) and put a reference to that memory address into your data object lo_struct
. Now the interesting part: You dynamically create another data (object) and save the pointer to that new data into lo_struct
. Thus now lo_struct
doesn't refer to the new table line any longer, but to the newly created data from CREATE DATA
.
TL;DR In the first example you CREATE DATA
and save the reference to that data into the object where your field symbol <lfs_struct>
refers to, which is the new table line in ei_lines
. In the second example, however, you also create a new table line and refer to it via lo_struct
, but when you CREATE DATA
afterwards, you store the reference to that new data again into lo_struct
, thus overwriting the original reference to the new table line.
Upvotes: 6