Ansicht
Dokumentation

ABAPSHEET_CONSTRUCTOR_EXPRESSIONS - SHEET CONSTRUCTOR EXPRESSIONS

ABAPSHEET_CONSTRUCTOR_EXPRESSIONS - SHEET CONSTRUCTOR EXPRESSIONS

CPI1466 during Backup   Vendor Master (General Section)  
Diese Dokumentation steht unter dem Copyright der SAP AG.
SAP E-Book

Arbeiten mit Konstruktorausdrücken

Dieser Spickzettel bietet einen Überblick über die Arbeit mit Konstruktorausdrücken. Darüber hinaus bietet er Ihnen eine nützliche Referenzsammlung von Syntax- und Quelltextstücken. Weitere Details und Syntaxoptionen finden Sie im jeweiligen Thema.

Einleitung

  • Wie der Name schon sagt, "konstruieren" diese Ausdrücke Ergebnisse zu eines bestimmten Typs. Dieser Daten- oder Objekttyp muss mit dem Operator übereinstimmen. Entweder wird der Typ explizit vor der ersten Klammer angegeben oder das Zeichen # kann angegeben werden, wenn der Typ implizit aus der Operandenposition abgeleitet werden kann. Das Zeichen # symbolisiert den Operandentyp. Wenn aus der Operandenposition kein Typ abgeleitet werden kann, kann bei manchen Konstruktoroperatoren auch der Typ aus den Argumenten in den Klammern abgeleitet werden.
  • Die Verwendung von Konstruktorausdrücken kann den Quelltext schlanker und lesbarer machen, da dasselbe mit weniger Anweisungen erreicht werden kann.
  • Abgesehen vom Konzept der Typinferenz ist ein anderes Konzept besonders in diesem Zusammenhang sehr praktisch: Inline-Deklaration.
  • Das bedeutet, dass eine Variable mit DATA(var) (oder einer unveränderlichen Variablen FINAL(var)) als Operand an der aktuellen Schreibpositiondeklariert werden kann. Dabei kann eine solche inline deklarierte Variable auf einmal den passenden Typ und das Ergebnis des Konstruktorausdrucks erhalten.

Hinweis

Die Konstruktion eines Ergebnisses, d.h. eines Zieldatenobjekts, impliziert, dass das Datenobjekt initialisiert wird. Es gibt jedoch Varianten, mit denen die Initialisierung vermieden werden kann.

VALUE

  • Ausdrücke mit dem Operator VALUE Operator konstruieren Strukturen und interne Tabellen basierend auf einem Datentyp (d.h. einem Tabellentyp oder einem strukturierten Typ).
  • Der Inhalt der resultierenden Struktur oder internen Tabelle wird durch die in Klammern angegebenen Parameter bestimmt.

Beispiel: Struktur

TYPES: BEGIN OF struc_type,
          a   TYPE i,
          b   TYPE c LENGTH 3,
        END OF struc_type.

DATA struc TYPE struc_type.

struc = VALUE #( a = 1 b = 'aaa' ). "Type inference

Wie oben erwähnt, wird hier das Konzept der Inline-Deklarationen dargestellt, was die ABAP-Programmierung vereinfacht. Es kann auf einmal eine neue Datenvariable konstruiert werden (z.B. mit DATA(...)), der gewünschte Typ mit dem Konstruktorausdruck versorgt werden und Werte zugewiesen werden.

DATA(structure) = VALUE struc_type( a = 2 b = 'bbb' ).

Beachten Sie, dass Initialwerte dadurch konstruiert werden können, dass die Komponentenangabe weggelassen oder kein Inhalt innerhalb der Klammern angegeben wird.

struc = VALUE #( a = 2 ). "Component b not specified, b remains initial
struc = VALUE #( a = 1 b = value #( ) ). "Explicit setting of initial value for a component
struc = VALUE #( ). "The whole structure is initial

Bezüglich interner Tabellen werden die Zeilenangaben in ein inneres Klammerpaar ( ... ) eingeschlossen. In den folgenden Beispielen werden einer Tabelle drei Zeilen hinzugefügt.

TYPES tab_type TYPE TABLE OF struc_type WITH EMPTY KEY.
DATA itab TYPE tab_type.

itab = VALUE #( ( a = 1 b = 'aaa' )
                ( a = 2 b = 'bbb' )
                ( a = 3 b = 'ccc' ) ).

"Table declared inline, explicit type specification
DATA(itab2) = VALUE tab_type( ( a = 1 b = 'aaa' )
                              ( a = 2 b = 'bbb' )
                              ( a = 3 b = 'ccc' ) ).

"Unstructured line types work without component names.
"Here, the table type is a string table.
DATA(itab3) = VALUE string_table( ( `abc` ) ( `def` ) ( `ghi` ) ).

Bei tiefen Strukturen und tiefen Tabellen ist die Verwendung von VALUE-Ausdrücken praktisch. Das folgende Beispiel demonstriert eine tiefe Struktur.

DATA: BEGIN OF deep_struc,
        a TYPE i,
        BEGIN OF nested_struc,
          y TYPE i,
          z TYPE c LENGTH 3,
        END OF nested_struc,
      END OF deep_struc.

deep_struc = VALUE #( a = 1 nested_struc = VALUE #( y = 2 z = 'abc' ) ).

Zusatz BASE: Ein Konstruktorausdruck ohne den Zusatz BASE initialisiert die Zielvariable. Daher kann der Zusatz verwendet werden, wenn eine Struktur oder interne Tabelle nicht von Grund auf neu aufgebaut werden soll, sondern vorhandener Inhalt beibehalten wird.

"Structure
struc = VALUE #( a = 1 b = 'aaa' ).

"struc is not initialized, only component b is modified, value of a is kept
struc = VALUE #( BASE struc b = 'bbb' ).

"Internal table
itab = VALUE #( ( a = 1 b = 'aaa' )
                ( a = 2 b = 'bbb' ) ).

"itab has two lines, two more are added instead of initializing the internal table first
itab = VALUE #( BASE itab
                ( a = 3 b = 'ccc' )
                ( a = 4 b = 'ddd' ) ).

Zusatz LINES OF: Alle oder einige Zeilen einer anderen Tabelle können in die interne Zieltabelle aufgenommen werden:

itab = VALUE #( ( a = 1 b = 'aaa' )
                ( a = 2 b = 'bbb' )
                ( LINES OF itab2 ) "All lines of itab2
                ( LINES OF itab3 FROM 2 TO 5 ) ). "Specific lines of itab3

Mit dem Inline-Aufbau von Strukturen und internen Tabellen kann die Deklaration zusätzlicher Variablen in vielen Kontexten, insbesondere ABAP-SQL-Anweisungen, vermieden werden. Siehe folgende Beispiele:

"Modification of individual internal table entries based on a structure created inline
MODIFY TABLE some_itab FROM VALUE #( a = 1 ... ). "Modifying a table line

INSERT VALUE #( a = 2 ... ) INTO TABLE some_itab. "Inserting a table line

DELETE TABLE some_itab FROM VALUE #( a = 3 ). "Deleting a table line

"Modifying multiple database table entries based on an internal table constructed inline
MODIFY scarr FROM TABLE @( VALUE #(
          ( carrid = 'XY'
            carrname = 'XY Airlines'
            currcode = 'USD'
            url =  'some_url' )
          ( carrid = 'ZZ'
            carrname = 'ZZ Airways'
            currcode = 'EUR'
            url =  'some_url' )
          ) ).

Einige der hier erwähnten Zusätze und Konzepte sind auch für andere Konstruktorausdrücke weiter unten gültig, aber nicht unbedingt explizit erwähnt. Details zu den syntaktischen Möglichkeiten der Konstruktoroperatoren finden Sie in der ABAP-Schlüsselwortdokumentation.

CORRESPONDING

  • Die Komponenten oder Spalten des Zieldatenobjekts werden durch Zuweisungen der in den Klammern angegebenen Parameter gefüllt.
  • Achten Sie auf die Zuweisungs- und Konvertierungsregeln, um Fehler bei der Verwendung des Operators zu vermeiden. Es soll beispielsweise die Auswirkung der Zuordnung der Werte von gleichnamigen Feldern, die unterschiedliche Typen haben berücksichtigt werden (z.B. ein Feld ist vom Typ c, ein anderes Feld ist vom Typ string).

Die folgende Liste enthält eine Auswahl verschiedener möglicher Varianten für diesen Konstruktoroperator. Es gibt weitere Varianten wie den Zusatz EXACT, die Verwendung einer Umsetzungstabelle, die Option zum Verwerfen von Duplikaten oder RAP-spezifischenVarianten, die nicht Teil dieses Spickzettels sind. Die Details finden Sie im jeweiligen Thema.

  • BASE: Behält die ursprünglichen Werte bei. Anders als beispielsweise der Operator VALUE müssen die Klammern um BASE gesetzt werden.
  • MAPPING: Ermöglicht die Abbildung von Komponentennamen, d.h. eine Komponente einer Quellstruktur oder Quelltabelle kann einer anders benannten Komponente einer Zielstruktur oder Zieltabelle zugeordnet werden (z.B. MAPPING c1 = c2).
  • EXCEPT: Es können Komponenten angegeben werden, denen im Zieldatenobjekt kein Inhalt zugeordnet werden soll. Sie bleiben initial. Dabei werden namensgleiche Komponenten im Quell- und Zielobjekt von der Zuweisung ausgeschlossen, die nicht kompatibel oder konvertierbar sind, um Syntax- oder Laufzeitfehler zu vermeiden.
  • DEEP: Relevant für tiefe tabellarische Komponenten. Sie werden auf jeder Hierarchieebene aufgelöst und namensgleiche Komponenten werden zeilenweise zugewiesen.
  • $[DEEP$] APPENDING: Relevant für (tiefe) tabellarische Komponenten. Hiermit wird sichergestellt, dass die geschachtelten Zieltabellen nicht gelöscht werden. Ohne DEEP bewirkt dies, dass Zeilen der geschachtelten Quelltabelle über CORRESPONDING ohne Zusatz hinzugefügt werden. Die Wirkung von DEEP ist, dass Zeilen der geschachtelten Quelltabelle über CORRESPONDING mit dem Zusatz DEEP hinzugefügt werden.

Im ausführbaren Beispiel wird die Wirkung der Varianten demonstriert:

struc2 = CORRESPONDING #( struc1 ).
tab2 = CORRESPONDING #( tab1 ).

"BASE
struc2 = CORRESPONDING #( BASE ( struc2 ) struc1 ).
tab2 = CORRESPONDING #( BASE ( tab2 ) tab1 ).

"MAPPING/EXACT
struc2 = CORRESPONDING #( struc1 MAPPING comp1 = comp2 ).
tab2 = CORRESPONDING #( tab1 EXCEPT comp1 ).

"Complex assignments with deep components using further additions
st_deep2 = CORRESPONDING #( DEEP st_deep1 ).
st_deep2 = CORRESPONDING #( DEEP BASE ( st_deep2 ) st_deep1 ).
st_deep2 = CORRESPONDING #( APPENDING ( st_deep2 ) st_deep1 ).
st_deep2 = CORRESPONDING #( DEEP APPENDING ( st_deep2 ) st_deep1 ).

Hinweis

Operator CORRESPONDING versus MOVE-CORRESPONDING: Obwohl die Funktionalität gleich ist, ist zu beachten, dass, wie der Name impliziert, die Konstruktoroperatoren "konstruieren" und - ohne den Zusatz BASE - Zielobjekte initialisiert werden. Daher sind die folgenden beiden Anweisungen nicht identisch:

struc2 = CORRESPONDING #( struc1 ).
MOVE-CORRESPONDING struc1 TO struc2. "Not matching components are not initialized

NEW

  • Der Operator hat die gleichen Möglichkeiten, ein Ergebnis zu konstruieren wie der Operator VALUE und ersetzt grundsätzlich CREATE DATA und CREATE OBJECT.
  • Beim Anlegen von Instanzen ist der Typname eines Ausdrucks mit NEW der Name einer Klasse (wenn der Name nicht mit #abgeleitet werden kann). Entweder bleibt der Inhalt innerhalb der Klammern leer oder, falls eine Konstruktormethode definiert ist, ist der Inhalt eine Liste von Parameterbindungen für die Konstruktormethode.
  • Ein großer Vorteil der Verwendung von NEW für die Objekterzeugung ist die Methodenverkettung, d.h. es muss keine zusätzliche Variable deklariert werden.

Beispiele:

"Data references
"Declare data reference variables
DATA dref1 TYPE REF TO i.    "Complete type
DATA dref2 TYPE REF TO data. "Generic type

"Create anonymous data objects
dref1 = NEW #( ).
dref2 = NEW string( ).

"Directly assigning values
dref1 = NEW #( 123 ).
dref2 = NEW string( `hallo` ).

"Use inline declarations to omit a prior declaration of a variable.
DATA(dref3) = NEW i( 456 ).

"Object references
"Declare object reference variables
DATA oref1 TYPE REF TO cl1. "Class without constructor
DATA oref2 TYPE REF TO cl2. "Class with constructor

"Create instances of classes
oref1 = NEW #( ).
"List the parameter bindings for the constructor method
"If there's only one parameter, the explicit specification of the
"parameter name is not needed and the value can be specified directly
oref2 = NEW #( p1 = ... p2 = ... ).

"Use inline declaration
DATA(oref2) = NEW cl2( p1 = ... p2 = ... ).

"Method chaining
"Assume the method meth has an importing parameter int of type REF TO i
... = NEW cl1( )->meth( int = NEW #( 5 ) ).

CONV

  • Der Operator CONV erzwingt Konvertierungen von einem Typ in einen anderen und erzeugt ein geeignetes Ergebnis.

  • Der Operator ist besonders geeignet, um die Deklaration von Hilfsvariablen zu vermeiden.

Beispiele:

DATA(a) = CONV decfloat34( 1 / 5 ). "0.2
DATA(b) = 1 / 5. "Comparison with an expression without CONV; result is 0

Exkurs: Strukturen und interne Tabellen können wie oben beschrieben mit dem Operator VALUE konstruiert werden. Die Verwendung dieses Operators zur Konstruktion elementarer Datenobjekte ist außer der Erzeugung eines Datenobjekts mit Initialwert wie DATA(str) = VALUE string( ). nicht möglich. Der Operator CONV schließt diese Lücke. In einigen Fällen ist die Verwendung von CONV jedoch redundant.

DATA(c) = CONV decfloat34( '0.4' ).
"Instead of
DATA d TYPE decfloat34 VALUE '0.4'.

"Redundant conversion
DATA(e) = `hallo`. "Derives the string type automatically.
"DATA(f) = CONV string( `hallo` ). "Produces a syntax warning

EXACT

Beispiele:

"Leads to a data loss when converting to a data object accepting only a single character
TRY.
  DATA(exact1) = EXACT abap_bool( 'XY' ).
  CATCH CX_SY_CONVERSION_DATA_LOSS INTO DATA(error1).
ENDTRY.

"The calculation cannot be executed exactly; a rounding is necessary
TRY.
  DATA(exact2) = EXACT decfloat34( 1 / 3 ).
  CATCH CX_SY_CONVERSION_ROUNDING INTO DATA(error2).
ENDTRY.

REF

  • Der hinter REF und direkt vor der ersten Klammer angegebene Typ bestimmt den statischen Typ des Ergebnisses.
  • Der Operator ersetzt GET REFERENCE und ist besonders geeignet, um die Deklaration von Hilfsvariablen zu vermeiden, die nur notwendig sind, um beispielsweise Datenreferenzvariablen als Aktualparameter anzugeben.

Beispiele:

"Data references
"Declare data object and assign value
DATA number TYPE i VALUE 5.

"Declare data reference variable
DATA dref_a TYPE REF TO i.

"Get references
dref_a = REF #( number ).
DATA(dref_b) = REF string( `hallo` ). "Inline declaration and explicit type specification

"Object references
DATA(oref_a) = NEW some_class( ).
DATA(oref_b) = REF #( oref_a ).

CAST

  • Mit dem Operator CAST können Upcasts und Downcasts durchgeführt und eine Referenzvariable des statischen Typs als Ergebnis erzeugt werden.
  • Der Operator ist besonders geeignet, um die Deklaration von Hilfsvariablen zu vermeiden, die nur für einen Downcast notwendig sind.

Beispiele für Run Time Type Identification (RTTI):

"Getting component information
DATA(components) =
  CAST cl_abap_structdescr(
    cl_abap_typedescr=>describe_by_data( some_object ) )->components.

"Getting method information
DATA(methods) =
  CAST cl_abap_objectdescr(
    cl_abap_objectdescr=>describe_by_name( 'LOCAL_CLASS' )
        )->methods.

COND

  • Es kann mehrere logische Ausdrücke geben, die mit WHEN eingeleitet werden, gefolgt von der Angabe des Ergebnisses hinter THEN. Wenn keiner der logischen Ausdrücke wahr ist, kann am Ende eine ELSE-Klausel angegeben werden. Wenn diese Klausel nicht angegeben ist, ist das Ergebnis dann der Initialwert des angegebenen oder abgeleiteten Datentyps.
  • Beachten Sie, dass alle hinter THEN angegebenen Operanden in den angegebenen oder abgeleiteten Datentyp konvertierbar sein müssen.

Beispiel:

DATA(b) = COND #( WHEN a BETWEEN 1 AND 3 THEN w
                  WHEN a > 4 THEN x
                  WHEN a IS INITIAL THEN y
                  ELSE z ).

SWITCH

Der Operator SWITCH ähnelt dem Operator COND und arbeitet im Stil von CASE-Anweisungen, d.h. er verwendet nur den Wert einer einzelnen Variablen, die in der Fallunterscheidung geprüft wird.

DATA(b) = SWITCH #( a
                    WHEN 1 THEN w
                    WHEN 2 THEN x
                    WHEN 3 THEN y
                    ELSE z ).

FILTER

  • Der Operator FILTER konstruiert eine interne Tabelle zeilenweise auf Basis einer vorhandenen Tabelle und Bedingungen, die in einer WHERE-Klausel angegeben sind.
  • Die Bedingungen können entweder auf Einzelwerten oder einer Filtertabellebasieren.
  • Zusätze:

  • EXCEPT: Die Angabe von EXCEPT bedeutet, dass die Zeilen der vorhandenen Tabelle verwendet werden, die nicht der in der WHERE-Klausel angegebenen Bedingung entsprechen. Wenn also EXCEPT nicht angegeben ist, werden die Zeilen der vorhandenen Tabelle verwendet, die die Bedingung erfüllen.

Beispiele:

DATA(f1) = FILTER #( tab WHERE comp > 5 ).
DATA(f2) = FILTER #( tab EXCEPT WHERE comp < 3 ).
DATA(f3) = FILTER #( tab USING KEY x WHERE comp = 4 ).

"Filtering based on another table
DATA(f3) = FILTER #( tab IN filter_tab
                     WHERE comp = 3 ).

REDUCE

  • Sie reduziert im Wesentlichen Mengen von Datenobjekten auf ein einzelnes Datenobjekt. Beispielsweise werden die numerischen Werte einer Tabellenspalte summiert. Dadurch wird die Gesamtzahl gebildet.

Das folgende Beispiel berechnet die Summe der Zahlen von 1 bis 10 mit dem Operator REDUCE :

DATA(sum) = REDUCE i( INIT s = 0
                      FOR  i = 1 UNTIL i > 10
                      NEXT s += i ) ). "sum: 55

Hinweise:

  • INIT ...: Es wird eine temporäre Variable angegeben, die einen Initialwert für die Ergebnisvariable setzt.
  • FOR ...: Stellt eine Schleife dar. Die Schleife wird so lange durchlaufen, bis die Bedingung hinter UNTIL erfüllt ist.
  • NEXT ...: Stellt die Zuweisung an die temporäre Variable nach jeder Iteration dar.
  • Nach Beendigung der Schleife wird der Zielvariablen der resultierende Wert zugewiesen.

Iterationsausdrücke mit FOR

  • Solche Ausdrücke sind in folgenden Kontexten möglich:
  • REDUCE: Das Reduzierungsergebnis wird in den Iterationsschritten erzeugt.

  • NEW und VALUE: Verwendung im Rahmen einer Schleife über interne Tabellen. In den Iterationsschritten werden neue Tabellenzeilen angelegt und in eine Zieltabelle eingefügt.

FOR ... WHILE (siehe FOR ... UNTIL im Abschnitt REDUCE ): Das folgende Beispiel mit REDUCE wirkt wie das obige Beispiel mit UNTIL.

DATA(sum) = REDUCE i( INIT y = 0
                      FOR n = 1 THEN n + 1 WHILE n < 11
                      NEXT y += n ).

FOR ... IN:

  • Der hinter FOR angegebene Operand stellt eine Iterationsvariable, d.h. einen Arbeitsbereich, dar, der die Daten während der Schleife über die Tabelle enthält.
  • Diese Variable ist nur innerhalb des FOR-Ausdrucks sichtbar, d.h. sie kann nicht außerhalb des Ausdrucks verwendet werden.
  • Der Typ der Variablen wird durch den Typ der hinter IN angegebenen internen Tabelle bestimmt.
  • Ein oder mehrere Iterationsausdrücke können mit FOR angegeben werden.
  • Die zurückzugebenden Komponenten, und daher auch die ganze Tabellenzeile, werden vor der schließenden Klammer innerhalb eines Klammerpaares angegeben.
  • Anders als in LOOP-Anweisungen ist kein Debugging für die sequentielle Verarbeitung möglich.

Beispiele für Tabellenschleifen und das Speichern von Werten in Zieltabellen:

"Loop across table and store the whole line in a new table;
"target table must have the same table type as source table itab;
"without the WHERE condition, all lines are considered
TYPES t_type LIKE itab.

... = VALUE t_type( FOR wa IN itab
                    "WHERE ( comp1 > 2 )
                    ( wa ) ).

"Store specific components having different names by specifying the assignment individually;
"assumption: target type is not compatible to the type of itab;
"a field mapping is provided; pay attention to potential type conversion
... = VALUE t_type( FOR wa IN itab
                    "WHERE ( comp1 > 2 )
                    ( compX = wa-comp1
                      compY = wa-comp2 ) ).

"Store specific components having the same names;
"assumption: Target type is not compatible to the type of itab;
"if there are identically named components in the table types, you might also use CORRESPONDING
... = VALUE t_type( FOR wa IN itab
                    "WHERE ( comp1 > 2 )
                    ( CORRESPONDING #( wa ) ) ).

"Multiple iteration expressions
... = VALUE t_type( FOR wa1 IN itab1 WHERE ( comp1 = 4 )
                    FOR wa2 IN itab2 WHERE ( comp2 > 5 )
                    FOR wa3 IN itab3 WHERE ( comp3 < 3 )
                    ( compX = wa1-comp1
                      compY = wa2-comp2
                      compZ = wa3-comp3 ) ).

LET-Ausdrücke

  • Mit LET-Ausdrücken können lokale Hilfsfelder (Variablen oder Feldsymbole) deklariert und Werte zugewiesen werden (der Typ wird aus dem definierten Wert abgeleitet), die in Konstruktorausdrücken verwendet werden, z.B. in Iterationsausdrücken mit FOR oder in Ergebnissen, die in den bedingten Ausdrücken von COND und SWITCH angegeben sind.
  • Beachten Sie, dass das Hilfsfeld nur in dem Kontext gültig ist, in dem der LET-Ausdruck angegeben ist.

Beispiele:

"Create a string table using a LET expression
DATA(str_tab) = VALUE string_table( LET it = `be` IN
                    ( |To { it } is to do| )
                    ( |To { it } or not to { it }| )
                    ( |To do is to { it }| )
                    ( |Do { it } do { it } do| ) ).

"Conditional expressions
DATA(a) = COND #( LET b = c IN
                  WHEN b > x THEN ...
                  WHEN b < y THEN ...
                  ...
                  ELSE ... ).

Demonstrationsprogramm

Im Beispiel Arbeiten mit Konstruktorausdrücken werden die oben erwähnten Konstruktorausdrücke in einem Programm demonstriert.






SUBST_MERGE_LIST - merge external lists to one complete list with #if... logic for R3up   Fill RESBD Structure from EBP Component Structure  
Diese Dokumentation steht unter dem Copyright der SAP AG.

Length: 40123 Date: 20240523 Time: 135815     sap01-206 ( 330 ms )