diff --git a/01_Internal_Tables.md b/01_Internal_Tables.md index 88aaa43..30602bb 100644 --- a/01_Internal_Tables.md +++ b/01_Internal_Tables.md @@ -7,8 +7,9 @@ - [Basic Properties of Internal Tables](#basic-properties-of-internal-tables) - [Table Keys in Internal Tables (Primary, Secondary, Standard, Empty)](#table-keys-in-internal-tables-primary-secondary-standard-empty) - [Creating Internal Tables and Types](#creating-internal-tables-and-types) - - [Filling and Copying Internal Tables](#filling-and-copying-internal-tables) - - [Using INSERT and APPEND Statements](#using-insert-and-append-statements) + - [Populating Internal Tables](#populating-internal-tables) + - [Copying Internal Tables](#copying-internal-tables) + - [Using INSERT and APPEND Statements to Populate Internal Tables](#using-insert-and-append-statements-to-populate-internal-tables) - [Creating and Filling Internal Tables Using Constructor Expressions](#creating-and-filling-internal-tables-using-constructor-expressions) - [Excursion: Using Internal Tables in ABAP SQL Statements](#excursion-using-internal-tables-in-abap-sql-statements) - [Reading Single Lines from Internal Tables](#reading-single-lines-from-internal-tables) @@ -405,9 +406,26 @@ SELECT * FROM zdemo_abap_fli INTO TABLE @FINAL(it_inline6).

⬆️ back to top

-## Filling and Copying Internal Tables +## Populating Internal Tables -### Using INSERT and APPEND Statements +### Copying Internal Tables + +A simple assignment without a constructor expression that **copies the content of another internal table** (note that the existing content in `itab` are deleted). The example below assumes that the source and target table have compatible line types. Using inline declaration is helpful to avoid an additional internal table declaration with an appropriate type. + +``` abap +itab = itab2. + +DATA(itab3) = itab. +FINAL(itab4) = itab. +``` + +> **💡 Note**
+> - Internal tables can only be assigned to internal tables. +> - Internal tables can be assigned to each other if their line types are [compatible](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencompatible_glosry.htm) or [convertible](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconvertible_glosry.htm). +> - An assignment can trigger an uncatchable exception if, for example, the target table is assigned a duplicate of a unique primary table key or secondary table. +> - More information: [Conversion Rules for Internal Tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_itab.htm) + +### Using INSERT and APPEND Statements to Populate Internal Tables You can use the ABAP keywords [`INSERT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinsert_itab.htm) @@ -579,15 +597,7 @@ itab = VALUE #( ( comp1 = a comp2 = b ...)                 ( LINES OF itab2 )                 ... ). ``` -A simple assignment without a constructor expression that **copies the content of another internal table** (note that the existing content in `itab` are deleted). The example below assumes that the source and target table have compatible line types. -``` abap -itab = itab2. -``` -> **💡 Note**
-> - Internal tables can only be assigned to internal tables. -> - Internal tables can be assigned to each other if their line types are [compatible](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencompatible_glosry.htm) or [convertible](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconvertible_glosry.htm). -> - An assignment can trigger an uncatchable exception if, for example, the target table is assigned a duplicate of a unique primary table key or secondary table. -> More information: [Conversion Rules for Internal Tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_itab.htm) + **Copying the content of another internal table** using the [`CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_corresponding.htm) operator. @@ -721,12 +731,12 @@ DATA(f11) = FILTER #( itab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE num = ``` > **💡 Note**
-> More constructor expressions are available to deal with internal tables. Find more information and examples in the [Constructor Expression cheat sheet](05_Constructor_Expressions.md). +> More constructor expressions are available to deal with internal tables, for example the `REDUCE` operator. Find more information and examples in the [Constructor Expression cheat sheet](05_Constructor_Expressions.md).

⬆️ back to top

### Excursion: Using Internal Tables in ABAP SQL Statements -For more details on ABAP SQL, see the cheat sheet on [ABAP SQL](03_ABAP_SQL.md). +For more details on ABAP SQL, see the [ABAP SQL](03_ABAP_SQL.md) cheat sheet. **Adding multiple lines from a database table to an internal table** using [`SELECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect.htm), @@ -814,7 +824,7 @@ Filling internal table from a table based on the existence of data in another table using the [`FOR ALL ENTRIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_all_entries.htm) addition. > **💡 Note**
-> Make sure that the internal table you are reading from is not initial. Therefore, it is recommended that you use a subquery as shown above: `... ( SELECT ... FROM @itab AS itab_alias WHERE ...`). +> Make sure that the internal table you are reading from is not initial. Therefore, it is recommended that you use a subquery as shown above: `... ( SELECT ... FROM @itab AS itab_alias WHERE ... ) ...`. ``` abap IF itab IS NOT INITIAL. @@ -1502,6 +1512,9 @@ FREE it. "Assignment using the VALUE operator without entries in the parentheses it = VALUE #( ). + +"The same applies to data reference variables pointing to internal tables. +it_ref = NEW #( ). ```

⬆️ back to top

diff --git a/02_Structures.md b/02_Structures.md index 9be8d3f..3ed13a2 100644 --- a/02_Structures.md +++ b/02_Structures.md @@ -127,7 +127,7 @@ DATA END OF struc. >- The keywords [`CLASS-DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass-data.htm) and [`CONSTANTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapconstants.htm) can also be used to create structures. In principle, they represent special cases of the general statement shown above. See the ABAP Keyword Documentation for more information. >- Structures can also be created [inline](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm) using [`DATA(...)`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_inline.htm) or [`FINAL(...)`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm), as shown below. -Creating structures using existing structured types: +**Creating structures using existing structured types** ``` abap "Local structured type @@ -156,10 +156,12 @@ DATA: struc_6 LIKE struc_1, ``` -Creating structures by inline declaration using `DATA(...)` +**Creating structures by inline declaration** + - This is particularly useful for declaring data objects at the [operand positions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm) where you actually need them. - In this way, you can avoid an extra declaration of the structure in different contexts. -- You can also use the [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) declaration operator to create [immutable variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenimmutable_variable_glosry.htm). +- You can use the declaration operator using `DATA(...)`. The [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) declaration operator is used to create [immutable variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenimmutable_variable_glosry.htm). +- You can also create structures using the `VALUE` operator (and also fill them as shown below). Without specifying component values in the parentheses, you create an initial structure. ``` abap "Structures created inline instead of an extra declared variable @@ -170,6 +172,14 @@ struc_9 = struc_1 DATA(struc_10) = struc_1. FINAL(struc_11) = struc_9. +"Using the VALUE operator +"A structure declaration as follows (without providing component +"value assignments) ... +DATA(struc_a) = VALUE struc_type( ). + +"... yields the same result as the following declaration. +DATA struc_b TYPE struc_type. + "Structures declared inline instead of an extra declared variable "Example: SELECT statement @@ -204,6 +214,36 @@ LOOP AT itab INTO DATA(wa_2). ENDLOOP. ``` +**Anonymous Structures** + +Using the instance operator [`NEW`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_new.htm) and [`CREATE DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcreate_data.htm) statements, you can create [anonymous data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm "Glossary Entry"), such as anonymous structures. +The `NEW` addition of the `INTO` clause of an ABAP SQL `SELECT` statement also creates an anonymous data object. +As outlined below, you can access the components or the entire data objects by [dereferencing](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendereferencing_operat_glosry.htm). +For more information, refer to the [Dynamic Programming](06_Dynamic_Programming.md) and [Constructor Expressions](05_Constructor_Expressions.md) cheat sheets. + +```abap +"Without assigning component values in the parentheses, the anonymous +"structure is initial. +DATA(struc_ref_a) = NEW struc_type( ). + +DATA struc_ref_b TYPE REF TO DATA. +struc_ref_b = NEW struc_type( ). + +"Multiple syntax options are available for CREATE DATA +"statements. See the cheat sheets mentioned. +CREATE DATA struc_ref_b TYPE struc_type. + +DATA struc_ref_c TYPE REF TO struc_type. +"Implicit data type definition +CREATE DATA struc_ref_c. + +"NEW addition of the INTO clause of an ABAP SQL SELECT statement +SELECT SINGLE carrid, carrname + FROM zdemo_abap_carr + WHERE carrid = char`LH` + INTO NEW @DATA(struc_ref_d). +``` +

⬆️ back to top

## Variants of Structures @@ -373,6 +413,17 @@ DATA(addr) = VALUE addr_struc( name   = `Mr. Duncan Pea`                    street = `Vegetable Lane 11`                    city   = `349875 Botanica` ). + +"Using the BASE addition to retain existing component values +addr = VALUE #( BASE addr street = `Some Street 1` ). +*NAME STREET CITY +*Mr. Duncan Pea Some Street 1 349875 Botanica + +"Without the BASE addition, the components are initialized +addr = VALUE #( street = `Another Street 2` ). +*NAME STREET CITY +* Another Street 2 + "Nesting value operators TYPES: BEGIN OF struc_nested, a TYPE i, @@ -537,6 +588,9 @@ CLEAR struc. "Note: An assignment using the VALUE operator without entries in the parentheses clears the structure. struc = VALUE #( ). + +"The same applies to data reference variables pointing to structures. +struc_ref = NEW #( ). ```

⬆️ back to top

diff --git a/06_Dynamic_Programming.md b/06_Dynamic_Programming.md index 58043f6..47f1489 100644 --- a/06_Dynamic_Programming.md +++ b/06_Dynamic_Programming.md @@ -543,26 +543,232 @@ SELECT SINGLE * INTO NEW @DATA(dref_8). "structure ``` -**Assignments between two data reference variables**. As mentioned above regarding the assignment, note that static types of both data -reference variables must be compatible. As a result of an assignment, both the target reference variable and the source reference variable point to the same data object. +**Assignments between two reference variables**. As mentioned above regarding the assignment, note that static types of both data +reference variables must be compatible. As a result of an assignment, both the target reference variable and the source reference variable point to the same (data) object. Excursion: Static vs. dynamic type, upcasts and downcasts - Data reference variables have ... - a [static type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_type_glosry.htm "Glossary Entry"). This is the type you specify when declaring the variable, i. e. `i` is the static type in this example: `DATA ref TYPE REF TO i.`. The static type can also be a generic data type: `DATA ref TYPE REF TO data.`. - - a [dynamic type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendynamic_type_glosry.htm "Glossary Entry"), the type of a data object to which the reference variable actually points to at runtime. + - a [dynamic type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendynamic_type_glosry.htm "Glossary Entry"), the type of a (data) object to which the reference variable actually points to at runtime. - For an assignment to work, the differentiation is particularly relevant since the following basic rule applies: The static type of the target reference variable must be more general than or the same as the dynamic type of the source reference variable. -- This is where the concepts of [upcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenup_cast_glosry.htm "Glossary Entry") and [downcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendown_cast_glosry.htm "Glossary Entry") enter the picture. - - Up and down? This concept originates from the idea of moving up or down in an [inheritance tree](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninheritance_tree_glosry.htm). In an assignment between reference variables, the target variable inherits the dynamic type of the source variable. - - Upcast: If the static type of the target variables is **less specific or the same** as the static type of the source variable, an assignment is possible. This includes, for example, assignments with the [assignment operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm) `=`. - - Downcast: If the static type of the target variable is **more specific** than the static type of the source variable, a check must be made at runtime before the assignment is done. If you indeed want to trigger such a downcast, you must do it explicitly in your code. You can do this, for example, using the +- This is where the concept of [upcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenup_cast_glosry.htm "Glossary Entry") and [downcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendown_cast_glosry.htm "Glossary Entry") enters the picture. + - This concept originates from the idea of moving up or down in an [inheritance tree](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninheritance_tree_glosry.htm). In an assignment between reference variables, the target variable inherits the dynamic type of the source variable. + - **Upcast**: If the static type of the target variables is **less specific or the same** as the static type of the source variable, an assignment is possible. This includes, for example, assignments with the [assignment operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm) `=`. + - **Downcast**: If the static type of the target variable is **more specific** than the static type of the source variable, a check must be made at runtime before the assignment is done. If you indeed want to trigger such a downcast, you must do it explicitly in your code. You can do this, for example, using the [constructor operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_operator_glosry.htm "Glossary Entry") [`CAST`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_cast.htm). In older code, you may see the use of the [`?=`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove_cast.htm) operator. - In contrast to a downcast, an upcast does not have to be done explicitly. However, you can - but need not - use the mentioned operators for upcasts, too. +The code snippet below demonstrates upcasts and downcasts with data reference variables, but also object reference variables to visualize moving up and down an inheritance tree. The examples in the code snippet use object reference variables to illustrate the class hierarchy of the [Runtime Type Services (RTTS)](#runtime-type-services-rtts), which is covered in more detail further down. You can find the hierarchy tree of the classes [here](#runtime-type-services-rtts). ``` abap -"Examples demonstrating up- and downcasts +"------------ Object reference variables ------------ + +"Static and dynamic types +"Defining an object reference variable with a static type +DATA tdo TYPE REF TO cl_abap_typedescr. + +"Retrieving type information +"The reference the reference variable points to is either cl_abap_elemdescr, +"cl_abap_enumdescr, cl_abap_refdescr, cl_abap_structdescr, or cl_abap_tabledescr. +"So, it points to one of the subclasses. The static type of tdo refers to +"cl_abap_typedescr, however, the dynamic type is one of the subclasses mentioned. +"in the case of the example, it is cl_abap_elemdescr. Check in the debugger. +DATA some_string TYPE string. +tdo = cl_abap_typedescr=>describe_by_data( some_string ). + +"Some more object reference variables +DATA tdo_super TYPE REF TO cl_abap_typedescr. +DATA tdo_elem TYPE REF TO cl_abap_elemdescr. +DATA tdo_data TYPE REF TO cl_abap_datadescr. +DATA tdo_gen_obj TYPE REF TO object. + +"------------ Upcasts ------------ + +"Moving up the inheritance tree +"Assignments: +"- If the static type of target variable is less specific or the same, an assignment works. +"- The target variable inherits the dynamic type of the source variable. + +"Static type of target variable is the same +tdo_super = tdo. + +"Examples for static types of target variables that are less specific +"Target variable has the generic type object +tdo_gen_obj = tdo. + +"Target variable is less specific because the direct superclass of cl_abap_elemdescr +"is cl_abap_datadescr +"Note: In the following three assignments, the target variable remains initial +"since the source variables do not (yet) point to any object. +tdo_data = tdo_elem. + +"Target variable is less specific because the direct superclass of cl_abap_datadescr +"is cl_abap_typedescr +tdo_super = tdo_data. + +"Target variable is less specific because the class cl_abap_typedescr is higher up in +"the inheritance tree than cl_abap_elemdescr +tdo_super = tdo_elem. + +"The casting happens implicitly. You can also excplicitly cast and use +"casting operators, but it is usually not required. +tdo_super = CAST #( tdo ). +tdo_super ?= tdo. + +"In combination with inline declarations, the CAST operator can be used to provide a +"reference variable with a more general type. +DATA(tdo_inl_cast) = CAST cl_abap_typedescr( tdo_elem ). + +CLEAR: tdo_super, tdo_elem, tdo_data, tdo_gen_obj. + +"------------ Downcasts ------------ + +"Moving down the inheritance tree +"Assignments: +"- If the static type of the target variable is more specific than the static type +" of the source variable, performing a check whether it is less specific or the same +" as the dynamic type of the source variable is required at runtime before the assignment +"- The target variable inherits the dynamic type of the source variable, however, the target +" variable can accept fewer dynamic types than the source variable +"- Downcasts are always performed explicitly using casting operators + +"Static type of the target is more specific +"object -> cl_abap_typedescr +tdo_super = CAST #( tdo_gen_obj ). +"cl_abap_typedescr -> cl_abap_datadescr +"Note: Here, the dynamic type of the source variable is cl_abap_elemdescr. +tdo_data = CAST #( tdo ). +"cl_abap_datadescr -> cl_abap_elemdescr +tdo_elem = CAST #( tdo_data ). +"cl_abap_typedescr -> cl_abap_elemdescr +tdo_elem = CAST #( tdo_super ). + +"------------ Error prevention in downcasts ------------ + +"In the examples above, the assignments work. The following code snippets +"deal with examples in which a downcast is not possible. An exception is +"raised. +DATA str_table TYPE string_table. +DATA tdo_table TYPE REF TO cl_abap_tabledescr. + +"With the following method call, tdo points to an object with +"reference to cl_abap_tabledescr. +tdo = cl_abap_typedescr=>describe_by_data( str_table ). + +"Therefore, the following downcast works. +tdo_table = CAST #( tdo ). + +"You could also achieve the same in one statement and with inline +"declaration. +DATA(tdo_table_2) = CAST cl_abap_tabledescr( cl_abap_typedescr=>describe_by_data( str_table ) ). + +"Example for an impossible downcast +"The generic object reference variable points to cl_abap_elemdescr after the following +"assignment. +tdo_gen_obj = cl_abap_typedescr=>describe_by_data( some_string ). + +"Without catching the exception, the runtime error MOVE_CAST_ERROR +"occurs. There is no syntax error at compile time. The static type of +"tdo_gen_obj is more generic than the static type of the target variable. +"The error occurs when trying to downcast, and the dynamic type is used. +TRY. + tdo_table = CAST #( tdo_gen_obj ). + CATCH cx_sy_move_cast_error. +ENDTRY. +"Note: tdo_table sill points to the reference as assigned above after trying +"to downcast in the TRY control structure. + +"Using CASE TYPE OF and IS INSTANCE OF statements, you can check if downcasts +"are possible. +"Note: In case of ... +"- non-initial object reference variables, the dynamic type is checked. +"- initial object reference variables, the static type is checked. + +"------------ IS INSTANCE OF ------------ +DATA some_tdo TYPE REF TO cl_abap_typedescr. +some_tdo = cl_abap_typedescr=>describe_by_data( str_table ). + +IF some_tdo IS INSTANCE OF cl_abap_elemdescr. + DATA(tdo_a) = CAST cl_abap_elemdescr( some_tdo ). +ELSE. + "This branch is executed. The downcast is not possible. + ... +ENDIF. + +IF some_tdo IS INSTANCE OF cl_abap_elemdescr. + DATA(tdo_b) = CAST cl_abap_elemdescr( some_tdo ). +ELSEIF some_tdo IS INSTANCE OF cl_abap_refdescr. + DATA(tdo_c) = CAST cl_abap_refdescr( some_tdo ). +ELSEIF some_tdo IS INSTANCE OF cl_abap_structdescr. + DATA(tdo_d) = CAST cl_abap_structdescr( some_tdo ). +ELSEIF some_tdo IS INSTANCE OF cl_abap_tabledescr. + "In this example, this branch is executed. With the check, + "you can make sure that the downcast is indeed possible. + DATA(tdo_e) = CAST cl_abap_tabledescr( some_tdo ). +ELSE. + ... +ENDIF. + +DATA initial_tdo TYPE REF TO cl_abap_typedescr. + +IF initial_tdo IS INSTANCE OF cl_abap_elemdescr. + DATA(tdo_f) = CAST cl_abap_elemdescr( some_tdo ). +ELSEIF initial_tdo IS INSTANCE OF cl_abap_refdescr. + DATA(tdo_g) = CAST cl_abap_refdescr( some_tdo ). +ELSEIF initial_tdo IS INSTANCE OF cl_abap_structdescr. + DATA(tdo_h) = CAST cl_abap_structdescr( some_tdo ). +ELSEIF initial_tdo IS INSTANCE OF cl_abap_tabledescr. + DATA(tdo_i) = CAST cl_abap_tabledescr( some_tdo ). +ELSE. + "In this example, this branch is executed. The static + "type of the initial object reference variable is used, + "which is cl_abap_typedescr here. + ... +ENDIF. + +"------------ CASE TYPE OF ------------ +"The examples are desinged similarly to the IS INSTANCE OF examples. + +DATA(dref) = REF #( str_table ). +some_tdo = cl_abap_typedescr=>describe_by_data( dref ). + +CASE TYPE OF some_tdo. + WHEN TYPE cl_abap_elemdescr. + DATA(tdo_j) = CAST cl_abap_elemdescr( some_tdo ). + WHEN TYPE cl_abap_refdescr. + "In this example, this branch is executed. With the check, + "you can make sure that the downcast is indeed possible. + DATA(tdo_k) = CAST cl_abap_refdescr( some_tdo ). + WHEN TYPE cl_abap_structdescr. + DATA(tdo_l) = CAST cl_abap_structdescr( some_tdo ). + WHEN TYPE cl_abap_tabledescr. + DATA(tdo_m) = CAST cl_abap_tabledescr( some_tdo ). + WHEN OTHERS. + ... +ENDCASE. + +"Example with initial object reference variable +CASE TYPE OF initial_tdo. + WHEN TYPE cl_abap_elemdescr. + DATA(tdo_n) = CAST cl_abap_elemdescr( some_tdo ). + WHEN TYPE cl_abap_refdescr. + DATA(tdo_o) = CAST cl_abap_refdescr( some_tdo ). + WHEN TYPE cl_abap_structdescr. + DATA(tdo_p) = CAST cl_abap_structdescr( some_tdo ). + WHEN TYPE cl_abap_tabledescr. + DATA(tdo_q) = CAST cl_abap_tabledescr( some_tdo ). + WHEN OTHERS. + "In this example, this branch is executed. The static + "type of the initial object reference variable is used, + "which is cl_abap_typedescr here. + ... +ENDCASE. + +********************************************************************** + +"------------ Data reference variables ------------ "Declaring data reference variables DATA ref1 TYPE REF TO i. @@ -594,7 +800,7 @@ ref6 = NEW i( 654 ). ref5 = CAST #( ref6 ). "Casting operator in older syntax -"ref5 ?= ref6. +ref5 ?= ref6. "Note: The cast operators can also but need not be specified for upcasts. ref4 = CAST #( ref3 ). diff --git a/07_String_Processing.md b/07_String_Processing.md index 50f0bfd..c98b65f 100644 --- a/07_String_Processing.md +++ b/07_String_Processing.md @@ -1820,6 +1820,17 @@ s2 = replace( val = s1 "Changing the source field directly with a REPLACE statement; same as above REPLACE PCRE `(.*?)PP(.*)` IN s1 WITH `$2#$1` IGNORING CASE. "pc app#ab a + +"ALL OCCURRENCES addition +REPLACE ALL OCCURRENCES OF PCRE `\s` IN s1 WITH `?`. "pc?app#ab?a + +REPLACE ALL OCCURRENCES OF PCRE `p.` IN s1 WITH `XY` "XY?aXY#ab?a + REPLACEMENT COUNT DATA(repl_cnt) "2 + RESULTS DATA(repl_res). + "repl_res: + "LINE OFFSET LENGTH + "0 0 2 + "0 4 2 ```

⬆️ back to top

diff --git a/16_Data_Types_and_Objects.md b/16_Data_Types_and_Objects.md index 32f33be..63df76e 100644 --- a/16_Data_Types_and_Objects.md +++ b/16_Data_Types_and_Objects.md @@ -854,6 +854,26 @@ SELECT * FROM zdemo_abap_carr INTO TABLE @DATA(itab_b3). SELECT * FROM zdemo_abap_carr INTO TABLE NEW @DATA(itab_ref). ``` +Inline declaration is useful for specifying data objects as actual parameters in method calls. It automatically determines the appropriate type, eliminating the need for additional variable declarations. However, it is important to note that inline declarations cannot be used when a method call is included in an expression. For example, if a method has both returning and exporting parameters, and you want to make a method call and assignement as shown in the example commented out, while also using inline declarations for the exporting parameters, this is not possible. This is because the assignment involves a method call expression on the right-hand side. + +```abap +"The following method calculates the difference in days, hours, minutes, +"and seconds of two time stamps. +"Check the F2 information of the 'diff' method. It has 4 exporting parameters. +"3 different types are involved. Using the inline declarations, the data +"objects receive the suitable types automatically. Extra variable declarations +"with suitable types can be avoided. +cl_abap_utclong=>diff( EXPORTING high = CONV utclong( '2024-01-01 15:30:00' ) + low = CONV utclong( '2023-12-24 14:20:40' ) + IMPORTING days = DATA(days) + hours = DATA(hours) + minutes = DATA(minutes) + seconds = DATA(seconds) ). + +"Not possible +"DATA(result) = some_cl=>some_meth( IMPORTING some_param = DATA(act_param) ). +``` +

⬆️ back to top

### Assigning References to Data Reference Variables