ABAP News
ABAP News
Effect
a data type or object type type that matches the operator and that can be derived
implicitly from the operand position,
Each constructor expression generates a result whose data type is determined using the
specified type. The parameters specified in parentheses are used to pass input values. The
following constructor operators exist:
The instance operator NEW is used to generate objects in operand positions. The
result is a reference variable of the static type type that points to the new object. The
input values determine the content of the new object.
The value operator VALUE is used to fill complex data objects with values in operand
positions, create initial values of any data type, or control the results of table
expressions. The result is a data object of the specified type type. The input values
determine the content of the result.
The conversion operator CONV is used for conversions between data types in operand
positions. The result is a data object of the specified type type produced by the
conversion from an input value.
The casting operator CAST is used for down casts of reference variables in operand
positions. The result is a reference variable of the static type type produced by the
assignment from an input value.
The reference operator REF is used to construct a data reference to a data object in
operand positions or to control the results of table expressions. The result is a data
reference variable.
The lossless operator EXACT is used to create a value in an operand position without
losing data. The result is a data object of the specified type, derived from a lossless
assignment or a lossless calculation.
The conditional operators COND and SWITCH are used to create values or raise class-
based exceptions in operand positions in accordance with conditions. The result is
determined by logical expressions or by a case distinction.
Effect
A constructor expression with the instance operator NEW creates an anonymous data object
or an instance of a class. The result is a reference variable that points to the new object. The
following can be specified for type:
The operator NEW works in the same way as the statement CREATE DATA dref TYPE
dtype, where dref stands for the result that points to the new anonymous data object.
The result is a data reference variable of the static type dtype. A constructor
expression of this type cannot be continued using a component selector.
A class class.
The operator NEW works in the same way as the statement CREATE OBJECT oref TYPE
class, where oref stands for the result that points to the new object. The result is an
object reference variable of the static type class. A constructor expression of this type
can be continued at general expression positions and functional positions, like an
object reference variable, using an object component selector ->, and can be used at
the same operand positions. Furthermore,
A single expression, which points to an attribute of the class using exactly one
following object component selector, can also be used as the target field of
assignments.
The # character.
If the data type required in an operand position is unique and fully recognizable, the #
character can be used instead of an explicitly specified type type and the operand type is used.
The same descriptions apply as for the CREATE statements. Once an object has been created, it
is provided with values using the parameters in parentheses. The syntax used in pass by
parameter depends on the type used. There are specialized categories of pass by parameter
for complex types.
Initial value for all types
dref = NEW #( ).
dref = NEW t_itab( ).
--
SELECT *
FROM t100
INTO wa
WHERE sprsl = sy-langu.
APPEND NEW #( wa ) TO dref_tab.
ENDSELECT.
Structures
Internal tables
Classes
CLASS c1 DEFINITION.
PUBLIC SECTION.
DATA a1 TYPE i.
METHODS: m1 RETURNING value(p) TYPE i,
m2.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD m1.
...
ENDMETHOD.
METHOD m2.
...
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
Return Value
If an instance of a class is created successfully, the instance operator NEW sets sy-subrc to 0.
Non-class-based exceptions of the instance constructor cannot be handled, which means that
sy-subrc is never set to a value other than 0. The return code sy-subrc is not set when
anonymous data objects are created.
Note
From a technical perspective, the instance operator NEW creates a new temporary reference
variable that points to the new object. The reference variable is used as the operand of a
statement and then deleted. It is deleted when the current statements is closed or after the
analysis of a relational expression once the logical value has been determined. The new object
is passed to the garbage collector if it is not passed to a heap reference or a field symbol after
the temporary reference variable is deleted.
Example
Creates an anonymous data object of the type i with the value 555 and an instance of a local
class class (derived implicitly from the static type of oref).
Effect
A constructor expression with the value operator VALUE creates a result of a data type
specified using type. The following can be specified for type:
The # character as a symbol for the operand type. Can be specified only if the data type
required in an operand position is unique and fully identifiable. An exception to this rule is
VALUE #( table_exp ).
The operator
structured types
table types
The content of the result is determined by the parameters specified in parentheses. The syntax
used in pass by parameter depends on the type used when the value was constructed. There
are specialized categories of pass by parameter for each possible type.
Structures
Internal tables
If a single table expression is specified as a parameter, VALUE does not construct a value and
controls the category of its result instead, as described in the related section.
Notes
Elementary data types and reference types cannot be specified explicitly for VALUE
using pass by value. Unlike when using the instance operator NEW, the correct result
can be achieved by using direct assignments. For this reason, it is not necessary to
specify unnamed arguments as single values when using NEW (and also not allowed).
The use of VALUE to control table expressions is not affected by this, since any valid
data type can be specified here.
Arithmetic calculations with the results of VALUE using pass by value are not possible.
This means that constructor expressions of this type cannot be specified directly in the
operand positions of arithmetic expressions. Constructor expressions using VALUE
used to control table expressions are not affected by this, if the table expressions can
be used for calculations using valid results.
From a technical perspective, the value operator VALUE creates a temporary data
object whose data type is determined by the specified type and whose content is
determined by the passed parameters. This data object is used as the operand of a
statement and then deleted. It is deleted when the current statements is closed or
after the analysis of a relational expression once the logical value has been
determined.
Example
Effect
A constructor expression with the conversion operator CONV converts the argument dobj to
the data type specified using type and creates an appropriate result. The following can be
specified for type:
The # character as a symbol for the operand type. Can be specified only if the data type
required in an operand position is unique and fully identifiable.
The parentheses must contain precisely one unnamed argument dobj that can be converted to
the data type type. dobj is a general expression position with the following restrictions:
The content of the result is determined by an assignment of the argument in accordance with
the associated conversion rule. If dobj is compatible with the data type type, CONV does not
need to be used and a syntax check warning is produced.
Notes
The conversion operator CONV is suitable for avoiding the declaration of helper
variables only needed to (for example)
The argument of CONV can itself be a calculation expression, which means that CONV
can be used within a calculation expression to transform results of subcalculations to a
specific type.
No empty parentheses can be specified after CONV to construct an initial value of the
specified type. The expression VALUE #( ) can be used to do this.
For reference types, the conversion operator CONV is not necessary, since these
involve only castings and no conversions. The operator CAST is used for castings.
Example
The method CONVERT_TO of the class CL_ABAP_CODEPAGE expects the data type string for
the input parameter SOURCE. CONV is used to convert a text field to this data type, directly in
the operand position.
file = cl_abap_codepage=>convert_to(
source = CONV string( text )
codepage = `UTF-8` ).
Example
Even though the internal table itab in the method meth1 has the same row type as the table
type of the parameter para of the method meth2, it cannot be passed directly due to its
different table category and key. CONV is used to convert itab to the required table type.
Effect
A conditional expression with the conditional operator COND has a result, result, that is
specified by logical expressions. Either a value with the data type specified by type is produced
or a class-based exception raised. The following can be specified for type:
If the data type required in an operand position is unique and fully identifiable, this
type is used.
If the operand type is not fully identifiable, an operand with a statically identifiable
type must be specified after the first THEN. This type is then used. In particular,
THROWs cannot be specified after THEN.
All operands specified after THEN must be convertible to the data type determined by type. In
the case of reference variables, an up cast must be possible.
In the parentheses, WHEN must be specified with at least once with any logical expression
log_exp. This can be followed by any number of WHENs with further logical expressions. An
ELSE can be specified at the end. The expression evaluates the logical expressions one after the
other and selects the result specified after THEN of the first logical expression whose result is
true. The selected result determines the result of the conditional expression. If none of the
logical expressions are true, the result specified after ELSE is selected. If ELSE is not specified,
the result is the initial value of the data type type.
Example
cl_demo_output=>display(
COND #( WHEN sy-timlo < '120000' THEN
|{ sy-timlo TIME = ISO } AM|
WHEN sy-timlo > '120000' AND sy-timlo < '240000' THEN
|{ CONV t( sy-timlo - 12 * 3600 ) TIME = ISO } PM|
WHEN sy-timlo = '120000' THEN
|High Noon|
ELSE
THROW cx_cant_be( ) ) ).
Effect
A conditional expression with the conditional operator SWITCH has a result, result, that is
specified by a case distinction. Either a value with the data type specified by type is produced
or a class-based exception raised. The same applies to type as to a conditional expression with
COND.
The first position operand in the parenthesis is the value checked in the case distinction. It is a
general expression position. It must be followed by at least one WHEN. Literals and constants
can be specified for const behind WHEN. It must be possible to compare them with operand.
This can be followed by any number of WHENs with further constant values. An ELSE can be
specified at the end. This expression compares the values of the operand operand with the
specified constant values, one by one, and chooses the result behind THEN for which the
values of operand and constant are identical for the first time. The selected result determines
the result of the conditional expression. If no matches are found, the result specified after ELSE
is selected. If ELSE is not specified, the result is the initial value of the data type type.
If an item specified after THEN or ELSE can be selected, either the result is set or a class-based
exception is raised, just as with a conditional expression COND.
Notes
A conditional expression with SWITCH has the same meaning as the following
conditional expression with COND:
Example
Conditional operator SWITCH in an operand position in a loop. The loop is exited when the
exception after ELSE is caught.
DATA(out) = cl_demo_output=>new( ).
DO.
TRY.
out->write(
SWITCH string( sy-index
WHEN 1 THEN 'one'
WHEN 2 THEN 'two'
WHEN 3 THEN 'three'
ELSE THROW cx_overflow( ) ) ).
CATCH cx_overflow.
out->display( ).
EXIT.
ENDTRY.
ENDDO.
Creating Objects and Values
DATA - Inline Declaration
The declaration operators
DATA(var)
FIELD-SYMBOLS <fs>.
can be used to make inline declarations in writer positions. In this way, declarations are made
in operational statements rather than in declaration statements. The declaration is made when
the program is compiled, regardless of whether the statement is actually executed.
Rule
Only make inline declarations in processing blocks that support local data. Use them as if they
were local declarations in the current statement block.
Details
If used correctly, inline declarations are an excellent way of making programs leaner and easier
to understand. However, since they they are used with a directly prefixed declaration
statement (like the short forms of the statement where they are specified), the guidelines for
declaration statements must be followed.
The rule dictating that no global program variables and field symbols are to be
declared also applies to inline declarations, without restrictions. For this reason,
statements with inline declarations should only be specified in processing blocks with
local data, namely procedures and preferably methods. If not, the variables and field
symbols declared inline would be global in the program, with all the drawbacks listed
in the description of the rule.
Inline declarations are an exception to the rule that local declarations should only be
made at the start of a procedure. They cannot be specified in operational statements,
which means that, unlike declaration statements, they cannot be specified at the start
of the procedure. Despite this, the restrictions stated in the rule for local declarations
are still valid for inline declarations. In particular, the validity of inline declarations is
not limited to their current statement block. Inline declarations should, therefore, only
be specified in less complex procedures, so making them easier to understand. The
variables and field symbols declared inline should only be used in the direct vicinity of
their declaration. Under no circumstances should a variable declared inline be
accessed dynamically before the declaration. When an inline declaration is specified in
a (conditional) control structure, it should usually only be accessed within this
statement block.
Bad example
Inline declaration of a field symbol <pattern> and two variables moff and mlen in a LOOP and
their later reuse in a different loop. At first glance, it appears that the declarations are only
valid in the first loop and only conditionally, but they are valid for the whole method and
unconditionally.
METHOD demo_method.
"IMPORTING i_tab1 TYPE TANDARD TABLE OF string
"IMPORTING i_tab2 TYPE TANDARD TABLE OF string
"IMPORTING i_text TYPE string
ENDMETHOD.
Good example
The field symbols and variables declared inline are only used locally in the their respective
loops. The fact that they are valid in the whole method is ignored, for the sake of simplicity. If
the field symbol and the variables are only to be declared once for both loops, they should be
declared at the start of the method using declaration statements.
METHOD demo_method.
"IMPORTING i_tab1 TYPE TANDARD TABLE OF string
"IMPORTING i_tab2 TYPE TANDARD TABLE OF string
"IMPORTING i_text TYPE string
IF i_tab1 IS NOT INITIAL.
LOOP AT i_tab1 ASSIGNING FIELD-SYMBOL(<pattern1>).
FIND <pattern1> IN i_text MATCH OFFSET DATA(moff1)
MATCH LENGTH DATA(mlen1).
...
ENDLOOP.
ENDIF.
ENDMETHOD.
DATA Example
Inline declaration of an internal table as a target field of an assignment and inline declaration
of an appropriate work area in a LOOP.
For small internal tables (less than 50 rows), the performance benefit for read
accesses is by far outweighed by the increased storage and administration load.
With tables that are subject to a large number of write accesses, the load incurred
by updating the secondary keys outweighs the performance benefit for read
accesses. With delayed updates and lazy updates in particular, the update load can
actually occur during a read access, which is where the optimization was required.
Unless the uniqueness of table entries is of absolute importance, it is better to
avoid using secondary hash keys.
Example
METHOD runtime.
DATA: jtab TYPE HASHED TABLE OF example_data=>struc
WITH UNIQUE KEY idx
WITH NON-UNIQUE SORTED KEY k1
COMPONENTS name postal_code.
DATA:
wa TYPE example_data=>struc,
t0 TYPE i,
t1 TYPE i.
* Fill table
example_data=>get_table(
EXPORTING lines = lines
IMPORTING table = jtab ).
* Perform measurement
GET RUN TIME FIELD t0.
DO n_mess TIMES.
READ TABLE jtab INTO wa
WITH KEY k1 COMPONENTS name = `Bugsy Siegel`
postal_code = 89033.
ENDDO.
GET RUN TIME FIELD t1.
* Calculate runtime
rtime = ( t1 - t0 ) / n_mess.
ENDMETHOD.
Example
Example
Example
DATA text_short TYPE c LENGTH 2.
DATA text_long TYPE c LENGTH 4.
text_short = 'AA'.
text_long = 'AAXX'.
"Expression
TRY.
text_short = itab[ KEY key COMPONENTS table_line = text_long ].
catch CX_SY_ITAB_LINE_NOT_FOUND.
...
ENDTRY.
cl_demo_output=>display( |Expression: { text_short }| ).
Effect
A table expression consists of an internal table itab, followed directly by a row (itab_line)
specified in square brackets [ ]. The expression finds the specified row in the internal table and
returns it as a result that can be used as follows:
Reader Positions
A table expression can be specified as a special expression variant for the memory area
in the statement ASSIGN.
Writer Positions
The structure component selector - can be used to access components of the row in question
and direct chainings [ ... ][ ... ] of multiple table expressions. Table expression cannot yet,
however, be specified on the left side of object component selector ->.
a table expression is used in the statement ASSIGN, where sy-subrc is set to the value
4,
when used in the predicate function line_exists, where the logical value "false" is
returned,
when used in the table function line_index, where the value 0 is returned.
Notes
Unlike other syntax representations in the ABAP key word documentation, the "[" and
"]" characters are part of the syntax.
In table expressions, the empty square brackets [] cannot be specified behind itab. In
other operand positions, these empty brackets distinguish the table body from header
lines.
Functions and constructor expressions cannot currently be specified for itab, but the
table expressions shown under Chainings are possible.
Duplicate selections (multiple reads performed on the same row of an internal table in
different expressions) must be avoided manually. In these cases, a selection should be
made before the statement and the result referenced by a field symbol or reference
variable.
Each table expression can be view as a short form for a variant of the statement READ
TABLE that enables reads to be performed on rows of internal tables in operand
positions.
Unlike READ TABLE, a table expression does not modify the value of the system field
sy-tabix.
Like the statement READ TABLE, a table expression is a single row read. If multiple
rows of an internal table are to be read, the statement LOOP generally displays better
performance than using table expressions in a loop.
Example
The content of the component carrid of the row of the internal table carrier_tab is passed to
the method get_spfli. In this table, the component carrname of the secondary key name has a
specific value.
TRY.
DATA(flight_tab) = cl_demo_spfli=>get_spfli(
carrier_tab[ KEY name
COMPONENTS carrname = 'United Airlines' ]-carrid ).
cl_demo_output=>display( flight_tab ).
CATCH cx_sy_itab_line_not_found.
cl_demo_output=>display( `Nothing found` ).
ENDTRY.
Example
Here, the first calculation with table rows is a bad example of how to use table expressions.
The same selection is made three times in the same statement. The second calculation shows
how this can be avoided by using an assignment to a field symbol.
"Bad example
itab[ table_line = 3 ] =
itab[ table_line = 3 ] * itab[ table_line = 3 ].
"Good example
ASSIGN itab[ table_line = 5 ] TO FIELD-SYMBOL(<fs>).
<fs> = <fs> * <fs>.
The table function lines returns the number of rows (or lines) in an internal table. The
argument arg is a functional operand position that expects an internal table. The return value
has the type i.
Notes
The function described here is one of the functions that can be used in the obsolete
extended functional operand positions, even if its argument is a single data object.
More specifically, a table expression or similar chaining can be specified for the
argument arg, if the result is an internal table.
The table function line_index returns the number of the row found using the table expression
table_exp with respect to the table index used. The return value has the type i.
The row itab_line found using the table expression must be defined by specifying a key. An
index cannot be specified. Alongside single table expressions, table_exp can also handle
chainings, whose result is a row of an internal table (i.e. they are closed using pointed
brackets). The result always refers to the row specified in the final pointed bracket and the key
read restrictions applies only to this pointed bracket.
Within line_index, an explicitly specified table key in the table row table_line of the table
expression is handled in the same way as a free search key specified for this table key.
The table index used makes reference to the specified key as follows:
If a search key is specified without a table key being specified explicitly, the number of
a found row is returned with respect to the primary table index; if a hashed table is
specified, the value -1 is returned.
If a table key is specified explicitly after KEY, the number of a found row is returned
with respect to the assigned table index. If the key is a hashed key, the value -1 is
returned.
If the row in question is not found, no exception is raised. The value 0 is returned instead. In
the case of chainings, of table expressions, the first unsuccessful from the left produces this
value.
Example
The index function can be used on chain expressions as follows, where the nested internal
table accessed is taken from the example for Chainings with Table Expressions. The first read
returns the value 1 for the first row of the innermost table. The second read returns the value
0, since there is no row available for the index read on the outermost table.
DATA(idx1) = line_index(
itab[ 2 ][ 2 ][ KEY primary_key table_line = 7 ] ).
DATA(idx2) = line_index(
itab[ 9 ][ 2 ][ KEY primary_key table_line = 7 ] ).