Ansicht
Dokumentation

ABAPSHEETS_DYNAMIC_PROG - SHEETS DYNAMIC PROG

ABAPSHEETS_DYNAMIC_PROG - SHEETS DYNAMIC PROG

SUBST_MERGE_LIST - merge external lists to one complete list with #if... logic for R3up   Addresses (Business Address Services)  
Diese Dokumentation steht unter dem Copyright der SAP AG.
SAP E-Book

Dynamische Programmierung

Dieser Spickzettel behandelt die Syntax und Konzepte im Zusammenhang mit der dynamischen Programmierung in ABAP. Er dient als zentrale Referenzsammlung der Grundlagen, unterstützt durch Beispiele. Lesen Sie auch den Abschnitt Dynamische Programmiertechniken in der ABAP-Schlüsselwortdokumentation, da er wichtige Aspekte enthält, die bei der dynamischen Programmierung im Allgemeinen berücksichtigt werden sollten (z. B. Sicherheitsaspekte oder die Vermeidung von Laufzeitfehlern).

Dynamisch?

Im Gegensatz zu "statischen" Aspekten gibt es einige Überlegungen bezüglich "dynamischer" Aspekte:

  • ABAP-Programme können sowohl dynamische als auch statische Teile umfassen.
  • Ein Datenobjekt, das in einem Programm deklariert wird, hat dedizierte technische Eigenschaften wie den Datentyp oder den tatsächlichen Namen des Datenobjekts, d.h., diese Eigenschaften sind dem Programm zur Kompilierungszeit bereits (statisch) bekannt und ändern sich während der Programmausführung nicht.
  • Andererseits kann es Anwendungsfälle geben, in denen diese Eigenschaften zum Zeitpunkt der Kompilierung noch nicht bekannt sind oder noch nicht ermittelt wurden.
  • Sie sind nur zur Laufzeit eines Programms bekannt, d.h. die Eigenschaften werden definiert und zur Laufzeit an Programme übergeben.
  • Ein Programm, das nicht mit einer bestimmten Tabellenart, sondern mit einer beliebigen Tabellenart arbeitet, muss vom Benutzer zuerst mit dem Tabellennamen identifiziert werden. Die im Programm zu verwendenden Tabellen haben sicherlich unterschiedliche Eigenschaften, Zeilentypen, Zeilenanzahl usw. Dennoch muss das Programm in der Lage sein, mit allen zu arbeiten, unabhängig davon, welche Tabelle verarbeitet wird.
  • Oder Informationen zu Datentypen und Datenobjekten müssen zur Laufzeit ermittelt oder sogar angelegt werden.

Die dynamische Programmierung ist ein leistungsfähiges Mittel, um ABAP-Programme flexibler und vielseitiger zu gestalten. Wie oben bereits erwähnt, müssen dynamische Programmiertechniken jedoch mit Vorsicht gehandhabt werden, und es müssen auch einige Nachteile berücksichtigt werden. Zum Beispiel:

  • Dynamische Eigenschaften, die in einem Programm implementiert sind, können vom ABAP-Kompilierer nicht überprüft oder analysiert werden. Die genauen Daten sind zum Zeitpunkt der Kompilierung nicht bekannt, sondern erst bei der Ausführung des Programms, was sich auch auf die Leistung auswirkt, da die Prüfungen zur Laufzeit durchgeführt werden müssen.

Exkurs: Feldsymbole und Datenreferenzen

Feldsymbole und Datenreferenzen unterstützen die dynamische Programmierung und das Arbeiten mit Datenobjekten, deren Eigenschaften erst zur Laufzeit bekannt sind.

Feldsymbole

Feldsymbole ...

  • können als Aliasnamen für vorhandene Datenobjekte betrachtet werden.
  • können nur verwendet werden, wenn sie zuerst einem Datenobjekt zugeordnet werden. Und falls zugewiesen, kann über den Feldsymbolnamen auf den Inhalt von Variablen zugegriffen werden.
  • verbrauchen keinen Platz, sondern dienen als eine Art Bezeichner für den jeweiligen Speicherbereich, der von einem dem Feldsymbol zugewiesenen Datenobjekt verwendet wird.
  • können in ABAP-Programmen so verwendet werden, als ob mit dem eigentlichen Datenobjekt gearbeitet würde.
  • sind besonders hilfreich, um zur Laufzeit auf Daten in Strukturen oder internen Tabellen zuzugreifen und diese zu bearbeiten, ohne die Daten irgendwo kopieren zu müssen, was die Leistung verbessert.

Feldsymbole deklarieren

Feldsymbole werden mit der Anweisung FIELD-SYMBOLS deklariert. Der Name des Feldsymbols wird in spitzen Klammern angegeben. Sie können entweder mit einem vollständigen Datentyp oder mit einem generischen Typ typisiert werden.

  • Für generische ABAP-Typen gibt es viele Möglichkeiten. Am prominentesten ist data, das für einen beliebigen Datentyp steht (der ältere generische Typ any hat die gleiche Wirkung). Weitere Informationen finden Sie im Abschnitt Generische ABAP-Typen.
  • Feldsymbole können nicht im Deklarationsteil von Klassen und Interfaces deklariert werden.
  • Nicht typisierte Feldsymbole werden in objektorientierten Kontexten nicht unterstützt.

Syntax:

"Complete types
FIELD-SYMBOLS: <fs_i>        TYPE i,
               <fs_spfli>    TYPE spfli,
               <fs_tab_type> TYPE LINE OF some_table_type,
               <fs_like>     LIKE some_data_object.

"Generic types
FIELD-SYMBOLS <fs_data>      TYPE data. "or TYPE any
FIELD-SYMBOLS <fs_any_table> TYPE any table.


Zuweisen von Datenobjekten

Bei der Zuweisung von Datenobjekten an Feldsymbole mit der Anweisung ASSIGN erhalten Feldsymbole alle Eigenschaften und Werte aus den Datenobjekten. Bei vollständig typisierten Feldsymbolen können nur Datenobjekte des gleichen Typs zugewiesen werden. Weitere dynamische Aspekte kommen mit dynamischer Zuweisung zum Tragen. Dies wird weiter unten behandelt.

Syntax:

"Data objects.
DATA: number TYPE i,
      struc  TYPE sflight,
      tab    TYPE string_table.

"Field symbols with complete types
FIELD-SYMBOLS: <fs_i>     TYPE i,
               <fs_struc> TYPE sflight,
               <fs_tab>   TYPE string_table.

"Generic type
FIELD-SYMBOLS <fs_gen> TYPE data.

"Assigning data objects to field symbols
ASSIGN number TO <fs_i>.
ASSIGN struc  TO <fs_struc>.
ASSIGN tab    TO <fs_tab>.
ASSIGN number TO <fs_gen>. "Could be any of the data objects

"You can also assign a particular component of a structure.
ASSIGN COMPONENT 2 OF STRUCTURE struc TO <fs_gen> "Second component of the structure.
ASSIGN COMPONENT 'CARRID' OF STRUCTURE struc TO <fs_gen>.

  • Wenn mit Feldsymbolen gearbeitet wird, müssen diese zugewiesen werden. Andernfalls kommt es zu einem Laufzeitfehler. Die Zuordnung kann mit dem folgenden logischen Ausdruck überprüft werden. Die Aussage ist wahr, wenn das Feldsymbol zugewiesen ist.
If <fs_i> IS ASSIGNED. ... ENDIF.
  • Die Zuweisung des Feldsymbols kann explizit aufgehoben werden. Danach zeigt das Feldsymbol nicht mehr auf ein Datenobjekt. Mit einer CLEAR-Anweisung wird nur der Wert initialisiert.
UNASSIGN <fs_i>.
  • Bei der Zuweisung von Datenobjekten an Feldsymbole ist auf kompatible Typen von Datenobjekt und Feldsymbol zu achten. Es gibt auch eine ABAP-Syntax, mit der ein Typ-Casting für inkompatible Typen durchgeführt werden kann. Durch die Angabe des konkreten Typs kann entweder implizit oder explizit ein Casting durchgeführt werden. Der Zusatz TYPE HANDLE ist für Run Time Type Services (RTTS)relevant.
DATA time TYPE c LENGTH 6 VALUE '123456'.
FIELD-SYMBOLS <fs1> TYPE sy-uzeit.
ASSIGN time TO <fs1> CASTING. "Implicit casting

FIELD-SYMBOLS <fs2> TYPE data.
ASSIGN time TO <fs2> CASTING TYPE sy-uzeit. "Explicit casting

Feldsymbole verwenden

Beim Zugriff auf Feldsymbole wird nur der Wert des zugewiesenen Datenobjekts angesprochen.

DATA: number TYPE i.
FIELD-SYMBOLS <fs_i> TYPE i.
ASSIGN number TO <fs_i>.

<fs_i> = 2.

Wie bereits erwähnt, werden Feldsymbole häufig beim Arbeiten mit internen Tabellen verwendet, beispielsweise in LOOP-Anweisungen. In diesem Zusammenhang sind Feldsymbole sehr praktisch. Ein tatsächliches Kopieren von Inhalten in einen Arbeitsbereich kann während der Schleife vermieden werden. Dadurch ist die Schleife insbesondere bei großen Tabellen deutlich schneller. Das Feldsymbol kann mit dem Zusatz ASSIGNING zugewiesen werden. Mit ASSIGNING FIELD-SYMBOL(...)kann das Feldsymbol direkt auf einmal deklariert und zugewiesen werden.

SELECT * FROM spfli INTO TABLE @DATA(itab).
FIELD-SYMBOLS <fs1> LIKE LINE OF itab.

LOOP AT itab ASSIGNING <fs1>.
  <fs1>-carrid = ... "The field symbol represents a line of the table.
  <fs1>-connid = ... "Components are accessed with the component selector. E. g. a new value is assigned.
  ...
ENDLOOP.

LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs2>).
  <fs2>-carrid = ...
  <fs2>-connid = ...
  ...
ENDLOOP.

Datenreferenzen

Datenreferenzen ...

  • sind ähnlich wie Feldsymbole, sind aber vielseitiger.
  • zeigen auf Datenobjekte im Speicher, d.h. sie enthalten die Speicherortadresse eines Datenobjekts

Datenreferenzvariablen ...

  • enthalten wie jedes andere Datenobjekt Werte. Der direkte Wert ist hier aber eine Referenz (d.h. er zeigt auf den Speicherort eines anderen Datenobjekts), so dass nicht direkt mit dem Wert gearbeitet werden kann.
  • zeigen zwar nur auf andere Datenobjekte, aber Datenobjekte, können beispielsweise auch als Komponenten in Strukturen oder Spalten interner Tabellen verwendet werden.

  • Datenreferenzvariablen werden wie Zeichenketten und interne Tabellen als tief betrachtet, da ihnen nicht allen ein eigener Speicherbereich zugeordnet ist. Zeichenketten und interne Tabellen werden intern über Referenzen adressiert.

Datenreferenzvariablen deklarieren

Datenreferenzvariablen können wie Feldsymbole mit DATA -Anweisungen und dem Zusatz REF TO sowohl vollständig als auch generisch deklariert werden. Der Typ hinter REF TO stellt den statischen Datentyp dar.

Datenreferenzvariablen zeigen bei ihrer Deklaration nicht auf ein Datenobjekt.

Syntax:

DATA: ref1 TYPE REF TO i, "Complete data type
      ref2 TYPE REF TO scarr, "Complete data type
      ref3 LIKE REF TO some_data_object,
      ref4 TYPE REF TO data. "Generic data type

Datenreferenzen zuweisen

Es gibt mehrere Möglichkeiten, Datenreferenzen zuzuordnen:

Datenreferenzen auf vorhandene Datenobjekte anlegen: Mit dem Referenzierungsoperator REF kann eine Datenreferenz auf ein vorhandenes Datenobjekt erzeugt werden. Die ältere Syntax GET REFERENCE wirkt wie die Verwendung des neueren Referenzierungsoperators.

DATA num TYPE i VALUE 5. "Declare data object
"Declare data reference variables
DATA ref1    TYPE REF TO i.
DATA ref_gen TYPE REF TO data.

"Create data references to data objects.
"The # sign means that the type is derived from the data object.
ref1    = REF #( num ).
ref_gen = REF #( num ).

"You can also use inline declarations to omit the explicit declaration.
DATA(ref2) = REF #( num ).
"You can explicitly specify the data type after REF.
DATA(ref3) = REF string( `hallo` ).

"Older syntax.
GET REFERENCE OF num INTO ref1.
GET REFERENCE OF num INTO DATA(ref4).

Neue Datenobjekte zur Laufzeit erzeugen: Ein sogenanntes anonymes Datenobjekt wird zur Laufzeit erzeugt indem die Referenz in die Variable eingefügt und den gewünschten Typ angegeben wird. Die Verwendung des Instanziierungsoperators NEW wird empfohlen. Die ältere Syntax CREATE DATA wirkt wie die Verwendung des neueren Instanziierungsoperators.

Syntax:

"Declare data reference variables
DATA ref1    TYPE REF TO i. "Complete type
DATA ref_gen TYPE REF TO data. "Generic type

"Create anonymous data objects
"Using the # sign and the explicit type: see REF #( ) above.
ref1    = NEW #( ).
ref_gen = NEW string( ).

"For directly assigning values, insert the values within the parentheses.
ref1 = NEW #( 123 ).

"Use inline declarations to omit a prior declaration of a variable.
DATA(ref2) = NEW i( 456 ).
TYPES i_table TYPE STANDARD TABLE OF i WITH EMPTY KEY.
DATA(ref3) = NEW i_table( ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ).

"Older syntax.
DATA ref4 TYPE REF TO string.
DATA ref5 TYPE REF TO data.

CREATE DATA ref4.
CREATE DATA ref5 TYPE p LENGTH 6 DECIMALS 2. "TYPE ... needed because of generic type data
CREATE DATA ref5 LIKE ref4.

Vorhandene Datenreferenzen zuweisen/kopieren: Eine Datenreferenz kann in eine andere kopiert werden. Die statischen Typen beider Datenreferenzvariablen müssen kompatibel sein und es wird nur die Referenz und nicht das Datenobjekt als solches kopiert. Das bedeutet, dass beim Kopieren beide Datenreferenzvariablen auf dasselbe Datenobjekt zeigen.

Datenreferenzvariablen haben sowohl einen statischen als auch einen dynamischen Typ. Beim Deklarieren einer Datenreferenzvariablen, z.B. DATA ref TYPE REF TO i., wird der statische Typ bestimmt. Dieser Typ ist entweder ein nicht generischer Typ (i im Beispiel) oder ein generischer Typ (wie data oder any; z. B. DATA ref TYPE REF TO data.). Der dynamische Typ wird zur Laufzeit des Programms ermittelt und stellt den Datentyp eines referenzierten Objektes dar. Insbesondere im Kontext der Zuordnung von Datenreferenzen (und Objektreferenzen) ist diese Unterscheidung relevant. Es gilt folgende Grundregel: Die Zuweisung eines Datenreferenzvariablen zu einem anderen Objekt oder Variablen ist dann möglich, wenn der statische Typ der Zielreferenzvariablen allgemeiner oder gleich dem dynamischen Typ der Quellreferenzvariablen ist. Eine statische Prüfung auf die Möglichkeit einer Zuweisung ist möglich. Die Zuweisung erfolgt über den Zuweisungsoperator =, mit dem ein Upcast automatisch ausgelöst wird. In anderen Fällen erfolgt ein Downcast. Dabei wird die Zuweisbarkeit erst zur Laufzeit überprüft. Für die Zuweisung von Datenreferenzvariablen muss der Downcast explizit über Casting-Operatoren ausgelöst werden, entweder mit dem Konstruktoroperator CAST oder dem älteren Operator ?=. Weitere Information ist im Thema Zuweisungsregeln für Referenzvariablen zu finden. Das folgende Beispiel zeigt Up- und Downcasts mit der Zuweisung von Datenreferenzvariablen, die mit einem vollständigen und generischen Datentyp typisiert sind:

Syntax:

"Declare data reference variables
DATA ref1 TYPE REF TO i.
DATA ref2 TYPE REF TO i.

ref1 = NEW #( 789 ).
ref2 = ref1. "Copy data reference

"Casting
DATA(ref3) = NEW i( 321 ). "Complete type
DATA ref4 TYPE REF TO data. "Generic type
ref4 = ref3. "Upcast

"Downcasts
DATA ref5 TYPE REF TO i.
DATA ref6 TYPE REF TO data. "Generic type
ref6 = NEW i( 654 ).
ref5 = CAST #( ref6 ).
ref5 ?= ref6.

Zugriff auf Datenreferenzen

Auf den Inhalt von Datenobjekten, auf die sich eine Datenreferenz bezieht, kann nur über die Dereferenzierung von Datenreferenzvariablen mit dem Dereferenzierungsoperator ->* zugegriffen werden.

  • Bei der Dereferenzierung einer Datenreferenzvariablen mit strukturiertem Datentyp kann über den Komponentenselektor -> auf einzelne Komponenten zugegriffen werden.
  • In älteren ABAP-Releases konnten Datenreferenzvariablen, die mit einem generischen Typ typisiert sind, nicht dereferenziert werden. Zuerst musste eine Zuweisung an ein Feldsymbol vorgenommen werden.

Syntax:

"Create data reference variables and assign values
DATA(ref_i)     = NEW i( 1 ).
DATA(ref_scarr) = NEW scarr( carrid = 'LH' carrname = 'Lufthansa' ).

"Generic type
DATA ref_gen TYPE REF TO data.
ref_gen = ref_i. "Copy reference

"Accessing
DATA(number) = ref_i->*. "Variable number receives the content.
ref_i->* = 10. "Content of referenced data object is changed.

IF ref_i->* > 5. "Data reference used in a logical expression.
...
ENDIF.

DATA(calc) = 1 + ref_gen->*. "Dereferenced generic type

"Structure
DATA(struc) = ref_scarr->*. "Complete structure
DATA(carrid) = ref_scarr->carrid. "Individual component
ref_scarr->carrid = 'UA'.
ref_scarr->*-carrname = 'United Airlines'. "This syntax also works but it's less comfortable.

  • Es kann geprüft werden, ob eine Datenreferenz dereferenziert werden kann, indem ein logischer Ausdruck mit IS BOUND verwendet wird:
IF ref IS BOUND. ... ENDIF.
  • Wenn eine Referenz explizit aus einer Datenreferenzvariablen entfernt werden soll, kann eine CLEAR -Anweisung verwendet werden. Der Garbage Collector übernimmt die Referenzentfernung jedoch automatisch, sobald die Daten nicht mehr von einer Referenz verwendet werden.
CLEAR ref.

Datenreferenzen verwenden

Einige Kontexte der Verwendung von Datenreferenzen sind:

Datenreferenzvariablen überschreiben: Eine Objektreferenz wird dann überschrieben wenn ein neues Objekt mit einer Referenzvariablen erzeugt wird, die bereits auf eine Instanz zeigt.

ref = NEW i( 1 ).
ref = NEW i( 2 ).

Datenreferenzen erhalten: Falls die Datenreferenzen erhalten bleiben sollen und das Überschreiben von Datenreferenzen bei Verwendung der gleichen Referenzvariablen vermieden werden soll, können die Referenzvariablen in internen Tabelle übernommen werden. Im folgenden Quelltext werden drei Objekte mit der gleichen Referenzvariablen erzeugt.

DATA: ref    TYPE REF TO data,
      itab   TYPE TABLE OF REF TO data,
      number TYPE i VALUE 0.

DO 3 TIMES.
  number += 1.  "Add up 1 to demonstrate a changed data object.
  "Create data reference and assign value
  "In the course of the loop, the variable gets overwritten.
  ref = NEW i( 1 ).
  itab = VALUE #( BASE itab ( ref ) ). "Adds the reference to itab.
ENDDO.

Interne Tabellen verarbeiten: Ähnlich wie bei der Verwendung von Feldsymbolen kann das Kopieren von Tabellenzeilen in einen Arbeitsbereich vermieden werden, z.B. in einer Schleife über Datenreferenzvariablen und einer REFERENCE INTO-Anweisung. Dabei ist die Verarbeitung interner Tabellen wesentlich schneller als das Kopieren von Tabellenzeilen in einen Arbeitsbereich. Im Quelltextausschnitt wird in der LOOP-Anweisung eine Inline-Deklaration verwendet.

SELECT * FROM spfli INTO TABLE @DATA(spfli_tab). "Fill an internal table.

LOOP AT spfli_tab REFERENCE INTO DATA(ref).
  ref->carrid = ...  "A component of the table line might be addressed.
  ...
ENDLOOP.

Datenreferenzvariablen als Teil von Strukturen und internen Tabellen: Im Gegensatz zu Feldsymbolen können Datenreferenzvariablen als Komponenten von Strukturen oder Spalten in internen Tabellen verwendet werden.

"Structure
DATA: BEGIN OF struc,
        num TYPE i,
        ref TYPE REF TO i,
      END OF struc.
struc2 = VALUE #( num = 1 ref = NEW #( 2 ) ). "Some value assignment.

"Internal table
DATA itab LIKE TABLE OF struc WITH EMPTY KEY.
itab[ 1 ]-ref->* = 123. "Some value assignment in the first table line.

Hinweis

Die Frage wäre nun, wann tatsächlich entweder ein Feldsymbol oder eine Datenreferenzvariable verwendet werden soll. Dies hängt vom jeweiligen Anwendungsfall ab. Datenreferenzvariablen sind jedoch hinsichtlich ihrer Verwendungsmöglichkeiten leistungsfähiger und passen besser in die moderne (objektorientierte) ABAP-Welt. Leseempfehlung: Dynamischer Zugriff auf Datenobjekte

Dynamische ABAP-Anweisungen

Dynamische Aspekte kommen insbesondere bei der Betrachtung dynamischer ABAP-Anweisungen zum Ausdruck. In diesem Zusammenhang können Tokens verwendet werden, die in Klammern gesetzt und als Operanden in viele ABAP-Anweisungen enthalten sind (z. B. SORT table BY (field_name).). Der Inhalt des Tokens ist zeichenartig und sollte in Großbuchstaben angegeben werden. Der Inhalt wird zur Laufzeit bestimmt, z.B. eine Benutzereingabe in einem Eingabefeld, das dann Teil einer ABAP-Anweisung ist.

Insbesondere in diesem Zusammenhang sind keine statischen Prüfungen möglich sind, d.h. bei einer ABAP-Anweisung, die ein solches Token verwendet, kann zum Zeitpunkt der Kompilierung nicht festgestellt werden, ob der übergebene Operand gültig ist. Dies kann zu Laufzeitfehlern führen.

Die folgenden dynamischen Angabeoptionen für tokens können verwendet werden:

Dynamische Angabe von Datenobjekten und Feldern: Die Namen von Datenobjekten und Feldern werden zur Laufzeit ermittelt. Zum Beispiel:

"The sorting is done by a field that is determined at runtime.
SORT itab BY (field_name).

"A field symbol is assigned a data object, here, an attribute of a class
ASSIGN class=>(attribute_name) TO FIELD-SYMBOL(<fs>).

Dynamische Angabe von Typen: Der Name eines Daten- oder Objekttyps wird zur Laufzeit ermittelt. Beispiele:

"Anonymous data objects are created using a type determined at runtime.
"Note that the NEW operator cannot be used here!
CREATE DATA ref TYPE (some_type).
CREATE DATA ref TYPE TABLE OF (some_type).

"Assigning a data object to a field symbol casting a type
ASSIGN dobj TO <fs> CASTING TYPE (some_type).

Dynamische Angabe von Klauseln in Anweisungen, z.B. ein Token, das die WHERE-Klauselbedingungen in einer SELECT-Anweisung enthält. Das Token kann auch eine interne Tabelle eines zeichenartigen Zeilentyps sein. Beispiele:

"Dynamic SELECT list
DATA(select_list) = `CARRID, CONNID, COUNTRYFR, COUNTRYTO`.
SELECT (select_list) FROM spfli INTO TABLE @itab.

"Dynamic FROM clause
DATA(table) = `SPFLI`.
SELECT * FROM (table) INTO TABLE @itab.

"Dynamic WHERE clause
DATA(where_clause) = `CARRID = 'LH'`.
SELECT * FROM spfli WHERE (where_clause) INTO TABLE @itab.

Dynamische Angabe von Prozeduren: Namen werden dynamisch angegeben, z.B. die Namen von Klassen und Methoden.

"Dynamic method calls
"Note that these calls require a CALL METHOD statement.
CALL METHOD class=>(meth). "Method dynamically specified.
CALL METHOD (class)=>meth. "Class dynamically specified.
CALL METHOD (class)=>(meth). "Class and method dynamically specified.
CALL METHOD class=>(meth) IMPORTING param = ... "Specifying parameters.

"Parameters and exceptions can also be specified dynamically in tables.
CALL METHOD class=>(meth) PARAMETER-TABLE ptab.
CALL METHOD class=>(meth) PARAMETER-TABLE ptab EXCEPTION-TABLE etab.

Bezüglich des Zusatzes PARAMETER-TABLE können Formalparametern dynamisch Aktualparameter über die Tabelle ptab vom Typ ABAP_PARMBIND_TAB zugeordnet werden. Die Tabelle muss gefüllt sein und für alle nicht optionalen Parameter eine Zeile haben. Der Zeilentyp ist ABAP_PARMBIND. Dabei sind folgende Felder relevant:

  • name: Der Name des Formalparameters.
  • kind: Gibt die Art des Parameters an, z.B. Import- oder Exportparameter. Die in der Klasse CL_ABAP_OBJECTDESCR definierten Konstanten können verwendet werden. Wenn die Methodensignatur einen Importparameter hat, muss sie hier als Exportparameter angegeben werden und umgekehrt.
  • value: Gibt eine Datenreferenz auf den Aktualparameter an.

Fehler lösen abfangbare Ausnahmen der Klasse CX_SY_DYN_CALL_ERROR aus. Mit dem Zusatz EXCEPTION-TABLE und einer internen Tabelle vom Typ ABAP_EXCPBIND_TAB können nicht klassenbasierte Ausnahmen behandelt werden.

Run Time Type Services (RTTS)

Die RTTS stellen eine Hierarchie von Typbeschreibungsklassen dar, die Methoden für Run Time Type Creation (RTTC) und Run Time Type Identification (RTTI) enthalten. Mit diesen Klassen ist Folgendes möglich:

  • Typinformationen zu Datenobjekten, Datentypen oder Instanzen zur Laufzeit abrufen.
  • neue Datentypen zur Laufzeit definieren und erzeugen.

Die Hierarchie der Typbeschreibungsklassen sieht wie folgt aus.

CL_ABAP_TYPEDESCR
  |
  |--CL_ABAP_DATADESCR
  |   |
  |   |--CL_ABAP_ELEMDESCR
  |   |   |
  |   |   |--CL_ABAP_ENUMDESCR
  |   |
  |   |--CL_ABAP_REFDESCR
  |   |--CL_ABAP_COMPLEXDESCR
  |       |
  |       |--CL_ABAP_STRUCTDESCR
  |       |--CL_ABAP_TABLEDESCR
  |
  |--CL_ABAP_OBJECTDESCR
     |
     |--CL_ABAP_CLASSDESCR
     |--CL_ABAP_INTFDESCR

Die Oberklasse CL_ABAP_TYPEDESCR hat also mehrere Unterklassen, z.B. um jede Art von Typ zu behandeln. Darunter befinden sich z.B. Strukturen oder Tabellen. Die Arbeit mit dieser Oberklasse und ihren Unterklassen bedeutet die Verwendung von Casts, insbesondere Downcasts. Die detaillierte Beschreibung aller Möglichkeiten für die Informationsbeschaffung und das Anlegen von Typen ist nicht im Umfang enthalten. Weitere Informationen finden Sie in den Informationen, Optionen und verschiedenen Methoden, die in der Klassendokumentation, z.B. über die F2-Hilfe in ADT, dokumentiert sind.

Die folgenden Beispiele zeigen den Abruf von Informationen. Anstelle der umständlichen zusätzlichen Deklaration von Datenreferenzvariablen können Inline-Deklarationen verwendet werden. Auch die Methodenverkettung ist praktisch.

"The properties of a type are retrieved.
DATA(some_type) = cl_abap_typedescr=>describe_by_data( var ).

"The components of a structure are retrieved.
"above, the describe_by_data method is used together with a variable.
DATA(components) = CAST cl_abap_structdescr(
  cl_abap_typedescr=>describe_by_data( some_struc )
       )->components.

"The attributes of a global class are retrieved. In contrast to the
"example above the describe_by_name method is used together with the actual name.
DATA(attributes) = CAST cl_abap_classdescr(
  cl_abap_classdescr=>describe_by_name( 'CL_DEMO_OUTPUT' )
       )->attributes.

Das folgende Beispiel zeigt das Anlegen eines internen Tabellentyps auf der Grundlage eines DDIC-Typs. Darüber hinaus wird auf der Grundlage dieses Typs eine interne Tabelle angelegt. Der Typ selbst ist eine sortierte Tabelle (auch hier können Konstanten verwendet werden). Eindeutige Schlüssel werden in einer eigenen Tabelle vom Typ ABAP_KEYDESCR_TAB definiert, die Teil des Methodenaufrufs cl_abap_tabledescr=>create ist.

Der Zusatz TYPE HANDLE wird als Teil der Anweisung CREATE DATA verwendet, die beim Bezug auf dynamisch erzeugte Datentypen verwendet wird.

"Get line type of DDIC table
DATA(line_type) =  CAST cl_abap_structdescr(
   cl_abap_tabledescr=>describe_by_name( `SCARR` ) ).

"Define primary table keys of internal table type to be created
DATA(key_tab) = VALUE abap_keydescr_tab( ( name = 'CARRID' )
                                         ( name = 'CARRNAME' ) ).

"Create internal table type
DATA(table_type) = cl_abap_tabledescr=>create(
    p_line_type  = line_type
    p_table_kind = cl_abap_tabledescr=>tablekind_sorted
    p_unique     = cl_abap_typedescr=>true
    p_key        = key_tab ).

"Create internal table based on the created table type
DATA ref_tab TYPE REF TO data.
CREATE DATA ref_tab TYPE HANDLE table_type.

Hinweis

Es gibt noch weitere dynamische Programmiertechniken wie die Generierung oder Ausführung von Programmen zur Laufzeit. Sie sind nicht Teil dieses Spickzettels. Weitere Details zur zugehörigen Syntax (z. B. GENERATE SUBROUTINE POOL, READ REPORT und INSERT REPORT) sind in der ABAP-Schlüsselwortdokumentation: Dynamische Programmentwicklung.

Demonstrationsprogramm

Das Beispiel Dynamische Programmierung demonstriert die Syntax und Konzepte der dynamischen Programmierung in einem Programm.






TXBHW - Original Tax Base Amount in Local Currency   General Material Data  
Diese Dokumentation steht unter dem Copyright der SAP AG.

Length: 39789 Date: 20240523 Time: 135756     sap01-206 ( 458 ms )