Update
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
- [Searching and Replacing Substrings in Internal Tables with Character-Like Data Types](#searching-and-replacing-substrings-in-internal-tables-with-character-like-data-types)
|
||||
- [Ranges Tables](#ranges-tables)
|
||||
- [Getting Table Type Information and Creating Internal Tables at Runtime](#getting-table-type-information-and-creating-internal-tables-at-runtime)
|
||||
- [Comparing Content of Compatible Internal Tables](#comparing-content-of-compatible-internal-tables)
|
||||
- [More Information](#more-information)
|
||||
- [Executable Example](#executable-example)
|
||||
|
||||
@@ -960,6 +961,123 @@ line = it[ b = 2 ].
|
||||
READ TABLE it INTO wa WITH KEY b = 2.
|
||||
```
|
||||
|
||||
Optimized read access using the `BINARY SEARCH` addition to the `READ TABLE` statement (find more details in the expandable section below):
|
||||
```abap
|
||||
READ TABLE itab WITH KEY ... BINARY SEARCH ...
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Expand to view more information and a code snippet</summary>
|
||||
<!-- -->
|
||||
|
||||
- `READ TABLE` without `BINARY SEARCH`: Table is accessed linearly
|
||||
- `READ TABLE` with `BINARY SEARCH`: Table is accessed using a binary search
|
||||
- Using the `BINARY SEARCH` addition is particularly more efficient for larger tables when accessing data often.
|
||||
- The table must be sorted in ascending order based on the keys being searched.
|
||||
- `BINARY SEARCH` is suitable for standard tables that do not have a secondary key defined and when you need to make multiple read accesses to the table (however, note the costs of a previous sorting)
|
||||
- `BINARY SEARCH` can only be used with index tables and not with hashed tables. If the table is sorted and the read access uses a free key, the addition can only be applied when the initial part of the table key is specified. I.e. if key components are `a`, `b`, and `c`, the addition can be used by specifying `a` alone, `a` and `b`, or `a`, `b`, and `c`. Not working (for example): `b` and `c` without `a`, or any other non-key component (because it cannot be sorted according to the non-key component).
|
||||
- Depending on the number of times you need to access the internal table, it is recommended to work with sorted tables or tables with secondary keys. If you only need to read one or a few data sets, consider the administrative costs of setting up the index.
|
||||
- Note: The `BINARY SEARCH` addition is not available for table expressions. If `KEY ...` is specified, an optimized search is performed by default. There are no performance differences between using the `READ TABLE` statement and table expressions.
|
||||
|
||||
The output of the following example, which includes multiple reads on standard internal tables using `READ TABLE` statements without `BINARY SEARCH` and with `BINARY SEARCH` demonstrates the performance gain. An excursion is included that shows read accesses in an internal table with a secondary table key.
|
||||
|
||||
```abap
|
||||
CLASS zcl_demo_test DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
INTERFACES if_oo_adt_classrun.
|
||||
PROTECTED SECTION.
|
||||
PRIVATE SECTION.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
|
||||
CLASS zcl_demo_test IMPLEMENTATION.
|
||||
METHOD if_oo_adt_classrun~main.
|
||||
"Line type and internal table declarations
|
||||
TYPES: BEGIN OF demo_struc,
|
||||
idx TYPE i,
|
||||
str TYPE string,
|
||||
num TYPE i,
|
||||
END OF demo_struc.
|
||||
|
||||
DATA: "Tables with empty primary table key
|
||||
itab_std1 TYPE STANDARD TABLE OF demo_struc WITH EMPTY KEY,
|
||||
itab_std2 LIKE itab_std1,
|
||||
"Table with empty primary table key, secondary table key specified
|
||||
itab_sec TYPE STANDARD TABLE OF demo_struc
|
||||
WITH EMPTY KEY
|
||||
WITH NON-UNIQUE SORTED KEY sk COMPONENTS str num.
|
||||
|
||||
"Populating internal tables
|
||||
DO 1000 TIMES.
|
||||
INSERT VALUE #( idx = sy-index
|
||||
str = |INDEX{ sy-index }|
|
||||
num = sy-index ) INTO TABLE itab_std1.
|
||||
ENDDO.
|
||||
itab_std2 = itab_std1.
|
||||
itab_sec = itab_std1.
|
||||
|
||||
"---- Reading without the BINARY SEARCH addition ----
|
||||
DATA(ts1) = utclong_current( ).
|
||||
DO 1000 TIMES.
|
||||
READ TABLE itab_std1
|
||||
WITH KEY str = `INDEX500` num = 500
|
||||
REFERENCE INTO DATA(dref1).
|
||||
ENDDO.
|
||||
DATA(ts2) = utclong_current( ).
|
||||
cl_abap_utclong=>diff( EXPORTING high = ts2
|
||||
low = ts1
|
||||
IMPORTING seconds = DATA(seconds) ).
|
||||
|
||||
out->write( `Elapsed time for the reads using READ TABLE without the BINARY SEARCH addition:` ).
|
||||
out->write( seconds ).
|
||||
out->write( repeat( val = `-` occ = 70 ) ).
|
||||
|
||||
"---- Reading with the BINARY SEARCH addition ----
|
||||
ts1 = utclong_current( ).
|
||||
"Sorting the internal table when using BINARY SEARCH
|
||||
"In this simple example, the internal table is populated by having the free key components
|
||||
"to be searched in ascending order anyway. This is to emphasize the requirement to
|
||||
"sort the (standard) internal table when using BINARY SEARCH.
|
||||
SORT itab_std2 BY str num.
|
||||
|
||||
DO 1000 TIMES.
|
||||
READ TABLE itab_std2
|
||||
WITH KEY str = `INDEX500` num = 500
|
||||
BINARY SEARCH
|
||||
REFERENCE INTO DATA(dref2).
|
||||
ENDDO.
|
||||
ts2 = utclong_current( ).
|
||||
cl_abap_utclong=>diff( EXPORTING high = ts2
|
||||
low = ts1
|
||||
IMPORTING seconds = seconds ).
|
||||
out->write( `Elapsed time for the reads using READ TABLE ... BINARY SEARCH ...:` ).
|
||||
out->write( seconds ).
|
||||
out->write( repeat( val = `-` occ = 70 ) ).
|
||||
|
||||
"---- Excursion: Reading with READ TABLE using a secondary table key ----
|
||||
ts1 = utclong_current( ).
|
||||
DO 1000 TIMES.
|
||||
READ TABLE itab_sec
|
||||
WITH TABLE KEY sk COMPONENTS str = `INDEX500` num = 500
|
||||
INTO DATA(dref3).
|
||||
ENDDO.
|
||||
ts2 = utclong_current( ).
|
||||
cl_abap_utclong=>diff( EXPORTING high = ts2
|
||||
low = ts1
|
||||
IMPORTING seconds = seconds ).
|
||||
out->write( `Elapsed time for the reads using READ TABLE and a secondary table key:` ).
|
||||
out->write( seconds ).
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Addressing Individual Components of Read Lines
|
||||
|
||||
When reading single lines in general, you can also address individual
|
||||
@@ -1518,7 +1636,8 @@ MODIFY it FROM line TRANSPORTING b c WHERE a < 5.
|
||||
You can use [`DELETE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdelete_itab.htm) statements to delete single and multiple lines in internal tables. The following additions can be used: `USING KEY` (for specifying a table key), `FROM`/`TO` (for specifying row ranges), `STEP` (for specifying the step size), and `WHERE` (for specifying conditions).
|
||||
|
||||
``` abap
|
||||
"Deleting via index
|
||||
"-------------- Deleting via index --------------
|
||||
|
||||
"Example: The first line in the table is deleted.
|
||||
DELETE it INDEX 1.
|
||||
|
||||
@@ -1531,7 +1650,8 @@ DELETE it INDEX 1 USING KEY primary_key.
|
||||
"Deleting an index range; FROM or TO alone can also be specified
|
||||
DELETE it FROM 2 TO 5.
|
||||
|
||||
"Deleting via keys
|
||||
"-------------- Deleting via keys --------------
|
||||
|
||||
"The line must have a compatible type to the tables line type and
|
||||
"include key values. The first found line with the corresponding keys
|
||||
"is deleted.
|
||||
@@ -1549,7 +1669,8 @@ DELETE TABLE it WITH TABLE KEY primary_key COMPONENTS a = 1.
|
||||
|
||||
DELETE TABLE it_sec WITH TABLE KEY sec_key COMPONENTS ...
|
||||
|
||||
"Deleting multiple lines based on a WHERE condition
|
||||
"---------- Deleting multiple lines based on a WHERE condition ----------
|
||||
|
||||
"Specifying the additions USING KEY, FROM, TO is also possible.
|
||||
DELETE it WHERE a < 6.
|
||||
|
||||
@@ -1564,6 +1685,58 @@ DATA(str_table) = VALUE string_table( ( `abcZ` ) ( `Zdef` ) ( `gZhi` )
|
||||
"All lines that begin with Z are to be deleted.
|
||||
DELETE str_table WHERE table_line CP `Z*`.
|
||||
"Result: abcZ / gZhi / pqrZ
|
||||
|
||||
"---------- Deleting the current line inside a LOOP statement ----------
|
||||
|
||||
"The following example illustrates deleting the current table line
|
||||
"using a DELETE statement within a LOOP statement. Lines with even
|
||||
"numbers are deleted.
|
||||
"Note:
|
||||
"- The short form of the DELETE statement always deletes the
|
||||
" current first line implicitly. It is only possible within a LOOP
|
||||
" statement and the delete operation is performed on the same internal
|
||||
" table.
|
||||
"- The field symbol (or reference variable) should not be used after
|
||||
" the DELETE statement any more.
|
||||
DATA itab1 TYPE TABLE OF i WITH EMPTY KEY.
|
||||
itab1 = VALUE #( ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ( 6 ) ( 7 ) ( 8 ) ( 9 ) ( 10 ) ).
|
||||
|
||||
LOOP AT itab1 ASSIGNING FIELD-SYMBOL(<fs>).
|
||||
IF <fs> MOD 2 = 0.
|
||||
DELETE itab1.
|
||||
ENDIF.
|
||||
ENDLOOP.
|
||||
|
||||
*Table content:
|
||||
*1
|
||||
*3
|
||||
*5
|
||||
*7
|
||||
*9
|
||||
|
||||
"The following, similar example (uneven numbers are deleted) uses a
|
||||
"table which is looped over by specifying the addition USING KEY.
|
||||
"In this case (using LOOP ... USING KEY ...), the short form of the
|
||||
"DELETE statement cannot be use. Use the DELETE statement with the
|
||||
"addition USING KEY loop_key to delete the current first line.
|
||||
"loop_key is a predefined name to be used with DELETE and within
|
||||
"loops that specify LOOP ... USING KEY .... No other key name is
|
||||
"possible here.
|
||||
DATA itab2 TYPE TABLE OF i WITH NON-UNIQUE KEY table_line.
|
||||
itab2 = VALUE #( ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ( 6 ) ( 7 ) ( 8 ) ( 9 ) ( 10 ) ).
|
||||
|
||||
LOOP AT itab2 USING KEY primary_key REFERENCE INTO DATA(dref2).
|
||||
IF dref2->* MOD 2 <> 0.
|
||||
DELETE itab2 USING KEY loop_key.
|
||||
ENDIF.
|
||||
ENDLOOP.
|
||||
|
||||
*Table content:
|
||||
*2
|
||||
*4
|
||||
*6
|
||||
*8
|
||||
*10
|
||||
```
|
||||
|
||||
### Deleting Adjacent Duplicate Lines
|
||||
@@ -1835,6 +2008,16 @@ For more information, see the [Dynamic Programming](06_Dynamic_Programming.md) c
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
### Comparing Content of Compatible Internal Tables
|
||||
|
||||
Using the methods of the `CL_ABAP_DIFF` class, you can compare the content of two compatible index tables.
|
||||
|
||||
Find ...
|
||||
- more information in the class documentation and in the [ABAP Keyword Documentation]([06_Dynamic_Programming.md](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencl_abap_diff.htm)).
|
||||
- a code snippet in the [Misc ABAP Classes](22_Misc_ABAP_Classes.md) cheat sheet.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
## More Information
|
||||
Topic [Internal Tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenitab.htm) in the ABAP Keyword Documentation.
|
||||
|
||||
|
||||
@@ -174,7 +174,8 @@ SELECT FROM source "What database table or view to read from
|
||||
internal tables as targets, the resulting table is a standard table
|
||||
and has an empty key which might have an impact when further
|
||||
processing the internal table entries. Find more information in the
|
||||
ABAP cheat sheet [Internal Tables](01_Internal_Tables.md). In newer ABAP releases, the declaration operator [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) can be used to declare immutable variables.
|
||||
ABAP cheat sheet [Internal Tables](01_Internal_Tables.md). The declaration operator [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) can be used to declare immutable variables.
|
||||
>- Many syntax examples in this cheat sheet show a selection from `dbtab` denoting a database table as a source. However, other data sources can also be specified.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
|
||||
@@ -11,21 +11,31 @@
|
||||
- [Visibility of Components](#visibility-of-components)
|
||||
- [Creating the Visibility Sections](#creating-the-visibility-sections)
|
||||
- [Defining Components](#defining-components)
|
||||
- [Class Attributes](#class-attributes)
|
||||
- [Methods](#methods)
|
||||
- [Method Parameter Interface](#method-parameter-interface)
|
||||
- [Constructors](#constructors)
|
||||
- [Working with Objects and Components](#working-with-objects-and-components)
|
||||
- [Declaring Reference Variables](#declaring-reference-variables)
|
||||
- [Creating Objects](#creating-objects)
|
||||
- [Assigning Reference Variables](#assigning-reference-variables)
|
||||
- [Working with Reference Variables](#working-with-reference-variables)
|
||||
- [Accessing Attributes](#accessing-attributes)
|
||||
- [Calling Methods](#calling-methods)
|
||||
- [Method Chaining](#method-chaining)
|
||||
- [Self-Reference me](#self-reference-me)
|
||||
- [Notes on Inheritance](#notes-on-inheritance)
|
||||
- [Notes on Polymorphism and Casting](#notes-on-polymorphism-and-casting)
|
||||
- [Notes on Interfaces](#notes-on-interfaces)
|
||||
- [Inheritance](#inheritance)
|
||||
- [Additions: ABSTRACT and FINAL](#additions-abstract-and-final)
|
||||
- [Redefining Methods](#redefining-methods)
|
||||
- [Polymorphism and Casting (Upcast/Downcast)](#polymorphism-and-casting-upcastdowncast)
|
||||
- [Demonstrating Upcasts and Downcasts Using the RTTS Inheritance Tree](#demonstrating-upcasts-and-downcasts-using-the-rtts-inheritance-tree)
|
||||
- [Interfaces](#interfaces)
|
||||
- [Defining Interfaces](#defining-interfaces)
|
||||
- [Implementing Interfaces](#implementing-interfaces)
|
||||
- [Interface Reference Variables and Accessing Objects](#interface-reference-variables-and-accessing-objects)
|
||||
- [Excursions](#excursions)
|
||||
- [Friendship](#friendship)
|
||||
- [Events](#events)
|
||||
- [Factory Methods and Singletons as Design Patterns](#factory-methods-and-singletons-as-design-patterns)
|
||||
- [Examples for Design Patterns: Factory Methods and Singletons](#examples-for-design-patterns-factory-methods-and-singletons)
|
||||
- [More Information](#more-information)
|
||||
- [Executable Example](#executable-example)
|
||||
|
||||
@@ -191,7 +201,7 @@ CLASS zcl_demo_test DEFINITION
|
||||
|
||||
PROTECTED SECTION.
|
||||
PRIVATE SECTION.
|
||||
"This methods uses types (data type c1 and the local exception class)
|
||||
"This method uses types (data type c1 and the local exception class)
|
||||
"defined in the CCDEF include
|
||||
METHODS calculate IMPORTING num1 TYPE i
|
||||
operator TYPE c1
|
||||
@@ -252,7 +262,7 @@ Code snippet for the CCDEF include:
|
||||
CLASS lcx_wrong_operator DEFINITION INHERITING FROM cx_static_check.
|
||||
ENDCLASS.
|
||||
|
||||
TYPES c1 type c length 1.
|
||||
TYPES c1 TYPE c LENGTH 1.
|
||||
```
|
||||
|
||||
Code snippet for the CCIMP include:
|
||||
@@ -267,7 +277,7 @@ ENDCLASS.
|
||||
CLASS lcl_demo IMPLEMENTATION.
|
||||
|
||||
METHOD say_hello.
|
||||
hi = |Hallo{ COND #( when name is supplied then ` ` && name ) }!|.
|
||||
hi = |Hallo{ COND #( WHEN name IS SUPPLIED THEN ` ` && name ) }!|.
|
||||
ENDMETHOD.
|
||||
|
||||
ENDCLASS.
|
||||
@@ -322,11 +332,6 @@ ENDCLASS.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
### Visibility of Components
|
||||
@@ -397,7 +402,7 @@ kinds of components are to be distinguished when, for example, looking at declar
|
||||
- [Static components](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_component_glosry.htm "Glossary Entry") (the declarations with `CLASS-`):
|
||||
Components that exist only once per class. They do no not exclusively exist for specific instances. They can be addressed using the name of the class.
|
||||
|
||||
**Attributes**
|
||||
#### Class Attributes
|
||||
|
||||
- The attributes of a class (or interface) mean the data objects declared within a
|
||||
class (or interface).
|
||||
@@ -428,6 +433,7 @@ can be used in the public visibility section. Effect:
|
||||
> - Can be read from outside of the class
|
||||
> - Cannot be changed from outside
|
||||
> - Can only be changed using methods of the class or its subclasses
|
||||
> - Note that when creating attributes in the public visibility section, they are globally visible and can therefore be globally used. Note the consequences on the users when changing attributes in the public visibility section (e.g. making an attribute read-only at a later point in time when, for example, other classes use the attribute).
|
||||
|
||||
Declaring attributes in visibility sections. In the code snippet below, all attributes are declared in the public section of a local class.
|
||||
``` abap
|
||||
@@ -462,7 +468,7 @@ ENDCLASS.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
**Methods**
|
||||
#### Methods
|
||||
|
||||
- Are internal
|
||||
[procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocedure_glosry.htm "Glossary Entry")
|
||||
@@ -486,7 +492,7 @@ ENDCLASS.
|
||||
You declare them using `METHODS` statements in a visibility
|
||||
section. Note that you must create an instance of a class first before using instance methods.
|
||||
|
||||
**Parameter Interface**
|
||||
#### Method Parameter Interface
|
||||
|
||||
In the simplest form, methods can have no parameter at all. Apart from that, methods can be defined with the following parameters:
|
||||
|
||||
@@ -544,7 +550,7 @@ In the simplest form, methods can have no parameter at all. Apart from that, met
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
**Constructors**
|
||||
#### Constructors
|
||||
|
||||
- [Constructors](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_glosry.htm "Glossary Entry")
|
||||
are special methods that are usually used for setting a defined
|
||||
@@ -670,7 +676,7 @@ for example, using `DATA`. In this case, the name of the class must be placed af
|
||||
instance constructor. See more information:
|
||||
[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennew_constructor_params_class.htm).
|
||||
- The operator
|
||||
basically replaces the syntax [`CREATE OBJECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcreate_object.htm) you might stumble on.
|
||||
basically replaces the syntax [`CREATE OBJECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcreate_object.htm) you might stumble on. However, `CREATE OBJECT` statements are still required (i.e. they are the only option, `NEW` is not possible for them) for creating objects dynamically. For more information, see the [Dynamic Programming](06_Dynamic_Programming.md) cheat sheet.
|
||||
|
||||
``` abap
|
||||
"Declaring object reference variable
|
||||
@@ -689,7 +695,11 @@ DATA(ref2) = NEW some_class( ). "Reference variable declared inline, explic
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
### Assigning Reference Variables
|
||||
### Working with Reference Variables
|
||||
Some examples for working with reference variables:
|
||||
|
||||
**Assigning Reference Variables**
|
||||
|
||||
To assign or copy
|
||||
reference variables, use the [assignment
|
||||
operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm "Glossary Entry")
|
||||
@@ -706,8 +716,6 @@ ref1 = NEW #( ).
|
||||
ref2 = ref1.
|
||||
```
|
||||
|
||||
More examples for dealing with object reference variables:
|
||||
|
||||
**Overwriting reference variables**: An [object
|
||||
reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_reference_glosry.htm "Glossary Entry")
|
||||
is overwritten when a new object is created with a reference variable
|
||||
@@ -955,7 +963,7 @@ ENDMETHOD.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
## Notes on Inheritance
|
||||
## Inheritance
|
||||
|
||||
- Concept: Deriving a new class (i. e.
|
||||
[subclass](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubclass_glosry.htm "Glossary Entry"))
|
||||
@@ -977,7 +985,8 @@ ENDMETHOD.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
**Excursion: Additions `ABSTRACT` and `FINAL`**
|
||||
### Additions: ABSTRACT and FINAL
|
||||
|
||||
- Both classes and methods can be defined with the additions `ABSTRACT` and `FINAL`.
|
||||
- `FINAL` with ...:
|
||||
- Classes: These classes cannot be inherited. All methods are automatically and implicitly `FINAL`. In this case, the addition `FINAL` cannot be used for methods.
|
||||
@@ -1009,7 +1018,7 @@ ENDCLASS.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
**Redefining Methods**
|
||||
### Redefining Methods
|
||||
|
||||
- Redefining methods is possible for the public and protected instance (not the static) methods of all preceding superclasses in a subclass (but only if the methods are not specified with `FINAL`).
|
||||
- In the declaration part of the subclass, you must specify the method as follows (and using the same method name):
|
||||
@@ -1032,7 +1041,7 @@ ENDCLASS.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
## Notes on Polymorphism and Casting
|
||||
## Polymorphism and Casting (Upcast/Downcast)
|
||||
|
||||
The object orientation concept
|
||||
[polymorphism](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpolymorphism_glosry.htm "Glossary Entry")
|
||||
@@ -1146,9 +1155,243 @@ DATA(rtti_d) = CAST cl_abap_structdescr(
|
||||
)->components.
|
||||
```
|
||||
|
||||
### Demonstrating Upcasts and Downcasts Using the RTTS Inheritance Tree
|
||||
|
||||
The examples in the following 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 in the [Dynamic Programming](06_Dynamic_Programming.md) cheat sheet.
|
||||
|
||||
Hierarchy tree of the classes:
|
||||
```abap
|
||||
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
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```abap
|
||||
"------------ 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.
|
||||
```
|
||||
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
## Notes on Interfaces
|
||||
## Interfaces
|
||||
|
||||
Interfaces ...
|
||||
|
||||
@@ -1174,7 +1417,7 @@ Interfaces ...
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
Defining interfaces:
|
||||
### Defining Interfaces
|
||||
- Can be done either globally in the repository or locally in an ABAP program.
|
||||
|
||||
``` abap
|
||||
@@ -1190,7 +1433,9 @@ INTERFACE intf.
|
||||
ENDINTERFACE.
|
||||
```
|
||||
|
||||
Implementing interfaces:
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
### Implementing Interfaces
|
||||
- A class can implement multiple interfaces.
|
||||
- Interfaces must be specified in the
|
||||
declaration part of a class using the statement
|
||||
@@ -1260,8 +1505,11 @@ CLASS cl_sub IMPLEMENTATION.
|
||||
ENDCLASS.
|
||||
```
|
||||
|
||||
Interface reference variables and accessing objects:
|
||||
- As mentioned above, addressing an object happens via an object reference variable with reference to a class.
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
### Interface Reference Variables and Accessing Objects
|
||||
|
||||
- Addressing an object happens via an object reference variable with reference to a class.
|
||||
- An interface variable can contain references to objects of classes that implement the corresponding interface.
|
||||
- You create an interface reference variable like this: `DATA i_ref TYPE REF TO intf.`
|
||||
|
||||
@@ -1414,7 +1662,7 @@ SET HANDLER handler3.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
### Factory Methods and Singletons as Design Patterns
|
||||
### Examples for Design Patterns: Factory Methods and Singletons
|
||||
|
||||
In object-oriented programming, there a plenty of design patterns. Covering these ones here to get a rough idea: factory methods and singletons. Both are relevant if you want to restrict or control the instantiation of a class by external users of this class.
|
||||
|
||||
|
||||
@@ -6,7 +6,18 @@
|
||||
- [Introduction](#introduction)
|
||||
- [Excursion: Field Symbols and Data References](#excursion-field-symbols-and-data-references)
|
||||
- [Field Symbols](#field-symbols)
|
||||
- [Declaring Field Symbols](#declaring-field-symbols)
|
||||
- [Assigning Data Objects](#assigning-data-objects)
|
||||
- [Examples Using Field Symbols](#examples-using-field-symbols)
|
||||
- [Generic Typing](#generic-typing)
|
||||
- [Data References](#data-references)
|
||||
- [Declaring Data Reference Variables](#declaring-data-reference-variables)
|
||||
- [Assigning References to Existing Data Objects](#assigning-references-to-existing-data-objects)
|
||||
- [Creating New Data Objects at Runtime (Anonymous Data Objects)](#creating-new-data-objects-at-runtime-anonymous-data-objects)
|
||||
- [Assignments Between Two Reference Variables (Static and Dynamic Type, Upcast and Downcast)](#assignments-between-two-reference-variables-static-and-dynamic-type-upcast-and-downcast)
|
||||
- [Addressing Data References](#addressing-data-references)
|
||||
- [Excursion: Generic Data References and Field Symbols](#excursion-generic-data-references-and-field-symbols)
|
||||
- [Examples Using Data References](#examples-using-data-references)
|
||||
- [Dynamic ABAP Statements](#dynamic-abap-statements)
|
||||
- [Dynamic ASSIGN Statements](#dynamic-assign-statements)
|
||||
- [Dynamically Specifying Data Types/Creating (Data) Objects](#dynamically-specifying-data-typescreating-data-objects)
|
||||
@@ -74,7 +85,9 @@ Field symbols ...
|
||||
- can be typed either with [generic data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengeneric_data_type_glosry.htm "Glossary Entry") or [complete data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomplete_data_type_glosry.htm "Glossary Entry").
|
||||
- are declared using the statement [`FIELD-SYMBOLS`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapfield-symbols.htm) or the [declaration operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_operator_glosry.htm) [`FIELD-SYMBOL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfield-symbol_inline.htm). Their names must be included between angle brackets.
|
||||
|
||||
**Declaring field symbols**
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
#### Declaring Field Symbols
|
||||
|
||||
Syntax:
|
||||
``` abap
|
||||
@@ -113,7 +126,9 @@ ENDLOOP.
|
||||
and
|
||||
[interfaces](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoo_intf_glosry.htm "Glossary Entry").
|
||||
|
||||
**Assigning data objects**
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
#### Assigning Data Objects
|
||||
|
||||
[`ASSIGN`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapassign.htm)
|
||||
statements assign the memory area of a data object to a field symbol.
|
||||
@@ -186,7 +201,9 @@ ASSIGN chars TO <fs2> CASTING LIKE chars_l4. "abcd
|
||||
> ```
|
||||
>- See more information on the addition `CASTING` [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapassign_casting.htm).
|
||||
|
||||
**Examples using field symbols**
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
#### Examples Using Field Symbols
|
||||
|
||||
``` abap
|
||||
"Assignments
|
||||
@@ -220,7 +237,13 @@ LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs2>).
|
||||
<fs2>-connid = ...
|
||||
...
|
||||
ENDLOOP.
|
||||
```
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
#### Generic Typing
|
||||
|
||||
``` abap
|
||||
"----------- Generic typing -----------
|
||||
"- Generic types are available with which formal parameters of methods or field symbols
|
||||
" can be specified.
|
||||
@@ -399,7 +422,9 @@ ASSIGN s-oref TO <object>.
|
||||
> [Object references](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_reference_glosry.htm "Glossary Entry")
|
||||
and [object reference variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_refer_variable_glosry.htm "Glossary Entry") are not part of this cheat sheet. To get more details, refer to the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_reference_type.htm) or the cheat sheet [ABAP Object Orientation](04_ABAP_Object_Orientation.md).
|
||||
|
||||
**Declaring data reference variables**
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
#### Declaring Data Reference Variables
|
||||
|
||||
``` abap
|
||||
"Example declarations of data reference variables with static types.
|
||||
@@ -416,8 +441,11 @@ DATA: ref_a TYPE REF TO i, "Complete data type
|
||||
As shown below, instead of the explicit declaration, inline declarations are also possible.
|
||||
See also the cheat sheet [Data Types and Data Objects](16_Data_Types_and_Objects.md).
|
||||
|
||||
**Assigning references to existing data objects** using the
|
||||
[reference operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_operator_glosry.htm "Glossary Entry")
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
#### Assigning References to Existing Data Objects
|
||||
|
||||
Assigning references to existing data objects [reference operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_operator_glosry.htm "Glossary Entry")
|
||||
`REF`.
|
||||
``` abap
|
||||
"Declaring a data object
|
||||
@@ -458,7 +486,9 @@ DATA(ref3) = REF some_type( ... ).
|
||||
"GET REFERENCE OF num INTO DATA(ref5).
|
||||
```
|
||||
|
||||
**Creating new data objects at runtime**:
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
#### Creating New Data Objects at Runtime (Anonymous Data Objects)
|
||||
[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") ...
|
||||
- are dynamically created at runtime.
|
||||
- are relevant if the data type is only known when the program is executed.
|
||||
@@ -543,7 +573,11 @@ SELECT SINGLE *
|
||||
INTO NEW @DATA(dref_8). "structure
|
||||
```
|
||||
|
||||
**Assignments between two reference variables**. As mentioned above regarding the assignment, note that static types of both data
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
#### Assignments Between Two Reference Variables (Static and Dynamic Type, Upcast and Downcast)
|
||||
|
||||
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
|
||||
@@ -806,7 +840,9 @@ ref5 ?= ref6.
|
||||
ref4 = CAST #( ref3 ).
|
||||
```
|
||||
|
||||
**Addressing data references**
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
#### Addressing Data References
|
||||
|
||||
Before addressing the content of data objects a data reference points to, you must dereference data reference variables. Use the
|
||||
[dereferencing operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendereferencing_operat_glosry.htm "Glossary Entry")
|
||||
@@ -864,7 +900,9 @@ DATA(ref_bound) = COND #( WHEN ref_carr IS BOUND THEN ref_carr->carrid ELSE `is
|
||||
CLEAR ref_carr.
|
||||
```
|
||||
|
||||
**Excursion: Generic data references and field symbols**
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
#### Excursion: Generic Data References and Field Symbols
|
||||
|
||||
```abap
|
||||
"Non-generic type
|
||||
@@ -917,7 +955,9 @@ DATA(num_tab_lines) = lines( dref->* ).
|
||||
DATA(idx) = line_index( dref->*[ ('CARRID') = 'LH' ] ).
|
||||
```
|
||||
|
||||
**Examples using data references**
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
#### Examples Using Data References
|
||||
|
||||
Some example contexts of using data references are as follows:
|
||||
|
||||
|
||||
@@ -847,7 +847,7 @@ Bullet points on selected `%` components:
|
||||
- Internal tables typed with BDEF derived types (`TYPE TABLE FOR ...`) are standard tables with an empty [primary table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprimary_table_key_glosry.htm) (`primary_key`).
|
||||
- Predefined [secondary table keys](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_table_key_glosry.htm) are available for many types.
|
||||
- These secondary table keys are always [sorted keys](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensorted_key_glosry.htm).
|
||||
- Currently available secondary table keys (as also visibile in one of the images above when using the F2 help in ADT):
|
||||
- Currently available secondary table keys (as also visible in one of the images above when using the F2 help in ADT):
|
||||
- `entity`: Includes `%key`
|
||||
- `cid`: Includes `%cid` or `%cid_ref`, and can - depending on the type - also include `%key` and `%pid`
|
||||
- `draft`: Available in draft scenarios; includes `%is_draft`; can also include `%key` and `%pid`
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
- [Loops Across Tables](#loops-across-tables)
|
||||
- [Calling Procedures](#calling-procedures)
|
||||
- [Excursion: RETURN](#excursion-return)
|
||||
- [Interrupting the Program Execution](#interrupting-the-program-execution)
|
||||
- [Handling Exceptions](#handling-exceptions)
|
||||
- [Notes on Exception Classes](#notes-on-exception-classes)
|
||||
- [Raising Exceptions](#raising-exceptions)
|
||||
@@ -613,6 +614,32 @@ ENDCLASS.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
## Interrupting the Program Execution
|
||||
|
||||
Using [`WAIT UP TO`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwait_up_to.htm) statements, you can interrupt the program execution by a specified number of seconds.
|
||||
|
||||
```abap
|
||||
"First retrieval of the current time stamp
|
||||
DATA(ts1) = utclong_current( ).
|
||||
...
|
||||
WAIT UP TO 1 SECONDS.
|
||||
...
|
||||
WAIT UP TO 3 SECONDS.
|
||||
...
|
||||
"Second retrieval of the current time stamp after the WAIT statements
|
||||
DATA(ts2) = utclong_current( ).
|
||||
"Calcularing the difference of the two time stamps
|
||||
cl_abap_utclong=>diff( EXPORTING high = ts2
|
||||
low = ts1
|
||||
IMPORTING seconds = DATA(seconds) ).
|
||||
|
||||
"The 'seconds' data object holding the delta of the time stamps
|
||||
"should be greater than 4.
|
||||
ASSERT seconds > 4.
|
||||
```
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
## Handling Exceptions
|
||||
- [Exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenexception_glosry.htm) ...
|
||||
- are events during the execution of an ABAP program that interrupt the program flow because it is not possible for the program to continue in a meaningful way. For such situations, you can implement an exception handling in which you can react on the situations appropriately. Consider, for example, the implementation of a simple calculation. If there is a division by zero, the program will be terminated with a [runtime error](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenruntime_error_glosry.htm) unless you handle the exception appropriately.
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
- [Runtime Type Services (RTTS)](#runtime-type-services-rtts)
|
||||
- [Assignments](#assignments)
|
||||
- [Information about Non-Initial Structure Components](#information-about-non-initial-structure-components)
|
||||
- [Comparing Content of Compatible Internal Tables](#comparing-content-of-compatible-internal-tables)
|
||||
- [Dynamic Programming](#dynamic-programming)
|
||||
- [Context Information](#context-information)
|
||||
- [XML/JSON](#xmljson)
|
||||
@@ -1266,6 +1267,114 @@ ENDCLASS.
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
## Comparing Content of Compatible Internal Tables
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td> Class </td> <td> Details/Code Snippet </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> <code>CL_ABAP_DIFF</code> </td>
|
||||
<td>
|
||||
Using the methods <code>diff</code> and <code>diff_with_line_ref</code> of the <code>CL_ABAP_DIFF</code> class, you can compare the content of two compatible index tables. The returning parameter is an internal table showing how the content of one internal table can be modified to match another one. <code>diff_with_line_ref</code> also returns a reference to the original table lines. Various importing parameters are available to adjust the comparison. Find more information in the class documentation and in the <a href="https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencl_abap_diff.htm">ABAP Keyword Documentation</a>.
|
||||
|
||||
<br>
|
||||
|
||||
```abap
|
||||
CLASS zcl_demo_test DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
INTERFACES if_oo_adt_classrun.
|
||||
PROTECTED SECTION.
|
||||
PRIVATE SECTION.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
|
||||
CLASS zcl_demo_test IMPLEMENTATION.
|
||||
METHOD if_oo_adt_classrun~main.
|
||||
TYPES: BEGIN OF s,
|
||||
a TYPE i,
|
||||
b TYPE string,
|
||||
c TYPE c LENGTH 3,
|
||||
END OF s.
|
||||
|
||||
DATA it1 TYPE TABLE OF s WITH EMPTY KEY.
|
||||
DATA it2 TYPE TABLE OF s WITH EMPTY KEY.
|
||||
|
||||
it1 = VALUE #(
|
||||
( a = 1 b = `aaa` c = 'zzz' )
|
||||
( a = 2 b = `bbb` c = 'yyy' )
|
||||
( a = 3 b = `ccc` c = 'xxx' )
|
||||
( a = 4 b = `ddd` c = 'www' )
|
||||
).
|
||||
|
||||
it2 = VALUE #(
|
||||
( a = 1 b = `aaa` c = 'zzz' )
|
||||
( a = 2 b = `#bb` c = 'yy#' )
|
||||
( a = 3 b = `cc` c = 'x' )
|
||||
( a = 4 b = `ddd` c = 'www' )
|
||||
( a = 5 b = `eee` c = 'vvv' )
|
||||
).
|
||||
|
||||
DATA(it3) = it1.
|
||||
DATA is_identical TYPE abap_bool.
|
||||
|
||||
DATA(comparison) = cl_abap_diff=>create( ).
|
||||
TRY.
|
||||
DATA(comp_res1) = comparison->diff( EXPORTING target = it2
|
||||
source = it1
|
||||
IMPORTING flag_identical = is_identical ).
|
||||
IF is_identical = abap_true.
|
||||
out->write( `The two internal tables have identical content.` ).
|
||||
CLEAR is_identical.
|
||||
ELSE.
|
||||
out->write( comp_res1 ).
|
||||
ENDIF.
|
||||
CATCH cx_abap_diff INTO DATA(error1).
|
||||
out->write( error1->get_text( ) ).
|
||||
ENDTRY.
|
||||
|
||||
TRY.
|
||||
DATA(comp_res2) = comparison->diff_with_line_ref( EXPORTING target = it2
|
||||
source = it1
|
||||
IMPORTING flag_identical = is_identical ).
|
||||
IF is_identical = abap_true.
|
||||
out->write( `The two internal tables have identical content.` ).
|
||||
CLEAR is_identical.
|
||||
ELSE.
|
||||
out->write( comp_res2 ).
|
||||
ENDIF.
|
||||
CATCH cx_abap_diff INTO DATA(error2).
|
||||
out->write( error2->get_text( ) ).
|
||||
ENDTRY.
|
||||
|
||||
TRY.
|
||||
DATA(comp_res3) = comparison->diff_with_line_ref( EXPORTING target = it3
|
||||
source = it1
|
||||
IMPORTING flag_identical = is_identical ).
|
||||
IF is_identical = abap_true.
|
||||
out->write( `The two internal tables have identical content.` ).
|
||||
CLEAR is_identical.
|
||||
ELSE.
|
||||
out->write( comp_res3 ).
|
||||
ENDIF.
|
||||
CATCH cx_abap_diff INTO DATA(error3).
|
||||
out->write( error2->get_text( ) ).
|
||||
ENDTRY.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
```
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||
|
||||
|
||||
## Dynamic Programming
|
||||
|
||||
|
||||
@@ -1258,6 +1258,6 @@ INTO @DATA(wa).
|
||||
[zcl_demo_abap_date_time](./src/zcl_demo_abap_date_time.clas.abap)
|
||||
|
||||
> **💡 Note**<br>
|
||||
> - The executable example covers the handling and processing of date, time, and time stamps. The snippets of this cheat sheets and more are included.
|
||||
> - The executable example covers the handling and processing of date, time, and time stamps. The snippets of this cheat sheet and more are included.
|
||||
> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples).
|
||||
> - [Disclaimer](README.md#%EF%B8%8F-disclaimer)
|
||||
Reference in New Issue
Block a user