The syntax supporting dynamic programming with ABAP has been expanded
continuously from release to release starting with ABAP/4. Our intention here is
not to trace this development; we will systematically introduce the entire scope.
Nonetheless, knowing about the history may help you understand why similar
concepts are sometimes implemented using widely differing syntax structures.
Since SAP Web AS 6.10 at the latest, ABAP offers at least the same options that
you may know from other programming languages. In contrast to these other
languages, ABAP can also rely on support by the ABAP Workbench, even in the
area of dynamic programming.
Lesson Objectives
After completing this lesson, you will be able to:
Create objects dynamically
Access class components and object components dynamically
Define field symbols
Define data references
Dereference data references
Generate data objects dynamically
Field Symbols
ABAP has featured field symbols as dereferenced pointers for some time now.
Field symbols allow you symbolic access to an existing data object. All
accesses that you make to the field symbol are made to the data object assigned
to it. Therefore, you can access only the content of the data object to which the
field symbol points. This technique is referred to as the value semantics of field
symbols.
You declare field symbols using the FIELD-SYMBOLS statement.
Caution: Note that the angle brackets (<>) in the field symbol name
are part of the syntax.
You use the ASSIGN statement to assign a data object to the field symbol. If the
field symbol is not typed (TYPE ANY), it adopts the type of the data object.
By specifying a type for the field symbol, you can ensure that only compatible
objects are assigned to it.
Example:
DATA: date TYPE d VALUE ’20040101’, time TYPE t.
FIELD-SYMBOLS:
ASSIGN: date TO
* possible?
The last statement represents a syntax error! Conversely, using the following
construction would trigger a runtime error:
FIELD-SYMBOLS:
You can use IS ASSIGNED to check whether a data object has been assigned to
a given field symbol. The UNASSIGN statement sets the field symbol to point
to nothing. Accordingly, the logical expression IS ASSIGNED is false after
this statement.
If you use the CASTING addition when you assign a data object to a field symbol
that has a different type, you can remove the restrictions of having to use the data
objects original type. The data object is then interpreted as though it had the
data type of the field symbol.
If you use the CASTING TYPE addition when you assign a data object to a field
symbol that has a different type, you can access the data object using the field
symbol as if the object had that explicitly specified type.
In the above example, note that the system field sy-datum is an elementary
character-type component of length 8.
You can also use type casting dynamically when you assign a data object to a
field symbol.
Example of Dynamic Type Casting:
PARAMETERS tabname TYPE dd02l-tabname.
DATA: line(65535) TYPE c.
FIELD-SYMBOLS
ASSIGN line TO
You can now use
the same type as the line type of the transparent table passed using tabname.
Note: This simple example will only work in Unicode systems if
tabname defines a character-like structure.
Accessing Attributes with Field Symbols
Field symbols can be used to access both static attributes and instance attributes,
by assigning their contents to the field symbols. In the syntax you replace the
data object by access to the attribute.
Attribute Access with ASSIGN Statement
ASSIGN class=>static_attribute TO
ASSIGN o_ref->instance_attribute TO
If field symbol
copied from the attributes during assignment.
This access can also be performed dynamically:
Dynamic Attribute Access with ASSIGN
Statement
DATA:
classname TYPE seoclsname VALUE ’CLASS’,
attributname TYPE seocpdname VALUE ’ATTRIBUTE’.
ASSIGN (classname)=>(attributname) TO
ASSIGN o_ref->(attributname) TO
Data References
Data references and object references were introduced alongside field symbols as
part of the enhancements in SAP R/3 4.6A. Since this point, ABAP features full
reference semantics.
Data reference variables contain data references, or pointers to data objects.
You can use the TYPE REF TO addition for the TYPES statement to define a
reference type for a data object. In this statement, you can either specify a data
type specifically or use TYPE REF TO data to choose the generic variant. In
this case, your data reference can point to any type of data object.
Note: Syntax item data represents a predefined identifier, comparable
to space and constructor.
The corresponding DATA statement defines the data reference variable itself.
Reference variables are data objects that can contain the address of any data object
(TYPE REF TO data) or a data object of the specified type.
Data references involve using reference semantics that is, when a data reference
variable is accessed, the data reference itself is addressed, which means any
changes affect the addresses.
Data reference variables are handled in ABAP like other data objects with an
elementary data type. This means a reference variable can be defined not only as a
single field, but also as the smallest indivisible unit of complex data objects such
as structures or internal tables.
After it is defined, a data reference variable is initial - that is, it contains a blank
pointer. For a data reference variable to contain a reference that points to a data
object, the GET REFERENCE OF statement has to be used to retrieve a reference
to an already defined data object.
A data reference variable can also be assigned an existing data reference from
another data reference variable, or a data object can be created dynamically with
the reference. (More about this later.)
Statically typed data references can be dereferenced directly using the
dereferencing operator ->*. This means they directly access the content of the
data object to which the reference points. To ensure compatibility, you have to
dereference generically typed data references (TYPE REF TO data) and
assign them to a field symbol, which you can then use to access the content. (This
method will be demonstrated again later.)
Therefore, the expression data_reference->* might be compared to the
expression
When data references are involved which are statically typed with a structure
type, you can address the components of the referenced data object directly, using
the component selector ->, and use them in any operand item.
Example:
DATA: wa TYPE sflight,
ref TYPE REF TO sflight.
GET REFERENCE OF wa INTO REF.
ref->fldate = ref->fldate + 5.
WRITE: / ref->seatsmax.
In this case, the component selector corresponds to the hyphen - in a regular
component access of structured data objects.
Validity of References – Logical Expression
... ref IS [NOT] BOUND ...
The ref IS [NOT] BOUND statement queries whether reference variable ref
contains a valid reference. ref has to be a data reference variable or object
reference variable here.
When a data reference is involved, this logical expression is true if it can be
dereferenced; When an object reference is involved, it is true if it points to an
object. The logical expression is always false if ref contains the null reference.
In comparison, the logical expression ... ref IS [NOT] INITIAL ...
merely lets you determine whether or not ref contains the null reference.
Dynamic Instantiation and Cast Assignments for Data
Objects
You can use data references and the CREATE DATA statement to generate data
objects at runtime analogous to class instances:
Instantiation of Data Objects at Runtime
DATA ref TYPE REF TO typename.
CREATE DATA ref.
After this, the ref data reference then points to the created data object. As an
alternative to the static variant, you can also determine the data type at runtime:
Generic Typing of Data Objects at Runtime
DATA ref TYPE REF TO data.
CREATE DATA ref TYPE typename.
To do so, the reference ref has to be typed generically with TYPE REF TO
data. In the following dynamic variant, the type name (typename) can also be
specified using a variable var_type:
Dynamic Instantiation of Data Objects at
Runtime
DATA ref TYPE REF TO data.
DATA var_type TYPE ... .
var_type = ... .
CREATE DATA ref TYPE (var_type).
In order to access the content of a data object that a data reference points to,
the reference has to be dereferenced in the way described above. To ensure
compatibility, however, a field symbol is required for generically typed data
references (TYPE REF TO data):
The ASSIGN ref_itab->* TO statement assigns the data
object which is referenced by reference variable ref_itab to field symbol
If the field symbol is typed completely generically, it assumes the data type of the
data object. If the field symbol is typed partially or fully, the system checks the
compatibility of the data types. You can also cast the assigned data object.
If the data reference is initial or invalid, dereferencing is not possible. In this case,
the field symbol is not changed and sy-subrc is set to four.
Generating Data Objects at Runtime –
Example Application
REPORT ... .
DATA:
ref_itab TYPE REF TO data,
ref_wa TYPE REF TO data.
FIELD-SYMBOLS:
PARAMETERS pa_tab TYPE dd02l-tabname DEFAULT ’SPFLI’.
START-OF-SELECTION.
CREATE DATA ref_itab TYPE STANDARD TABLE OF (pa_tab)
WITH NON-UNIQUE DEFAULT KEY.
ASSIGN ref_itab->* TO
SELECT * FROM (pa_tab)
INTO TABLE
UP TO 100 ROWS.
CREATE DATA ref_wa LIKE LINE OF
ASSIGN ref_wa->* TO
LOOP AT
DO.
ASSIGN COMPONENT sy-index OF STRUCTURE
IF sy-subrc NE 0.
NEW-LINE.
EXIT.
ENDIF.
WRITE
ENDDO.
ENDLOOP.
The example can display the content of any transparent table. You can make the
FROM clause of the SELECT statement dynamic.
For the INTO clause, you will need a data object that has a line type compatible
with that of the table being displayed. Since the name and thus the line type
of the table is not known until runtime, you should not create the data object
until then. Unlike conventional data objects, you can specify the type of a data
object created at runtime dynamically. The TYPE addition of the CREATE DATA
statement contains the name of the table, to ensure that the system always creates
the appropriate structure.
The statement ASSIGN ref_wa->* TO
the field symbol. The data type of the table is inherited by the field symbol so type
casting is no longer necessary. You can now write each data record from the
SELECT statement into the compatibly-typed data object using the field symbol
If you knew the component names, you could display the fields directly using
WRITE
the names of the components, nor how many of them there are. As a result, you
have to use the ASSIGN-COMPONENT variant for output: Each component in
structure
then output. When the loop runs out of components, the program requests the
next data record.
Analogous to object references, you can also use the CAST operator to copy data
references to reference variables whose static type is identical to the dynamic
type of the source reference. This is the case in the first example above, but not
in the second.
Note: If the cast assignment operator ?= were not used, these assignments
would not even pass a syntax check, because the source and target types
are incompatible.
If a data reference variable is typed statically, it passes on its type attributes when
it is assigned to a non-typed data reference. This can be very useful, especially
where the additional information of global data types is involved.
During dereferencing, the type of the reference variable, and not the type of the
data object to which the reference points, is decisive. This is illustrated in the
following example:
In the above example, reference variable REF_CITYTO is typed statically with a
data element. At runtime, it receives a reference to data object CITYFROM, which
has a different type. The reference is then dereferenced with the generically typed
field symbol
result, in a list output, for example, the field documentation for the data element.
Hint: To achieve a consistent result, the REF_CITYTO reference would
have to be typed generically or in agreement with data object CITYFROM.
Caution: This example has been designed specifically to show that the
type of a statically typed reference variable really is decisive.