CASTING TYPE HANDLE type_descr_obj.
```
- Dynamically specifying clauses in ABAP SQL statements
``` abap
"This snippet demonstrates a selection of possible dynamic
"specifications in ABAP SQL SELECT statements.
"Dynamic SELECT list
DATA(select_list) = `CARRID, CONNID, COUNTRYFR, COUNTRYTO`.
SELECT (select_list)
FROM zdemo_abap_fli
INTO TABLE ...
"Dynamic FROM clause
DATA(table) = `ZDEMO_ABAP_FLI`.
SELECT *
FROM (table)
INTO TABLE ...
"Excursion: Dynamic FROM clause and compatible target data object
DATA(db_table) = `ZDEMO_ABAP_CARR`.
DATA itab TYPE REF TO data.
CREATE DATA itab TYPE TABLE OF (db_table).
SELECT *
FROM (db_table)
INTO TABLE @itab->*.
"Similar to the NEW operator, you can use the addition NEW here
"to create an anonymous data object in place. The advantage is
"that the data type is constructed in a suitable way.
SELECT *
FROM (db_table)
INTO TABLE NEW @DATA(dref_tab).
"Dynamic WHERE clause
"This is an example for using an internal table with a
"character-like row type
DATA(where_clause) = VALUE string_table( ( `CARRID = 'LH'` )
( `OR CARRID = 'AA'` ) ).
SELECT *
FROM zdemo_abap_fli
WHERE (where_clause)
INTO TABLE ...
```
- Dynamic invoke: Dynamically specifying [procedure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocedure_glosry.htm "Glossary Entry") calls
``` abap
"Notes:
"- Dynamic method calls require a CALL METHOD statement.
"- The first 3 examples assume that there are no mandatory
" parameters defined for the method.
"- The example covers only static methods. Dynamic method calls
" for instance methods are also possible.
"Method dynamically specified
CALL METHOD class=>(meth).
"Class dynamically specified
CALL METHOD (class)=>meth.
"Class and method dynamically specified
CALL METHOD (class)=>(meth).
"Assigning actual parameters to the formal parameters statically
CALL METHOD class=>(meth) EXPORTING p1 = a1 p2 = a2 ...
IMPORTING p1 = a1 p2 = a2 ...
"Assigning actual parameters to the formal parameters dynamically
DATA ptab TYPE abap_parmbind_tab.
ptab = ...
CALL METHOD class=>(meth) PARAMETER-TABLE ptab.
"Notes on PARAMETER-TABLE ptab
"- The table (of type abap_parmbind_tab; line type is abap_parmbind)
" must be filled and have a line for all non-optional parameters.
"- Components: name -> formal parameter name
" kind -> kind of parameter, e. g. importing
" value -> pointer to appropriate actual parameter,
" is of type REF TO data
"The addition EXCEPTION-TABLE for exceptions is not dealt with here.
```
⬆️ back to top
## Runtime Type Services (RTTS)
[RTTS](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrun_time_type_services_glosry.htm "Glossary Entry")
represent a hierarchy of [type description classes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentype_class_glosry.htm "Glossary Entry")
containing methods for
- getting type information on data objects, data types or
[instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_glosry.htm "Glossary Entry")
at runtime ([Runtime Type Identification (RTTI)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrun_time_type_identific_glosry.htm "Glossary Entry")).
- defining and creating new data types as [type description objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentype_object_glosry.htm) at runtime ([Runtime Type Creation (RTTC)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrun_time_type_creation_glosry.htm "Glossary Entry")).
The hierarchy of type description classes is as follows.
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
So, the
[superclass](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensuperclass_glosry.htm "Glossary Entry")
`CL_ABAP_TYPEDESCR` has multiple
[subclasses](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubclass_glosry.htm "Glossary Entry"),
for example, to deal with each kind of type.
Working with this inheritance tree means making use of
[casts](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abencast_glosry.htm "Glossary Entry"),
especially
[downcasts](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendown_cast_glosry.htm "Glossary Entry") when retrieving information at runtime.
Detailing out all the possibilities for the information retrieval and
type creation is beyond scope. Check the information, options and
various methods that can be used in the class documentation, e. g. using
F2 help information in
[ADT](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenadt_glosry.htm "Glossary Entry"),
for more details.
⬆️ back to top
### Getting Type Information at Runtime
With RTTI, you can determine data types at runtime using description methods in type description classes.
To get the type information, you can get a reference to a type description object of a type, that is, an instance of a type description class.
The type properties are represented by attributes that are accessible through the type description object.
> **💡 Note**
> - For each type, there is exactly one type description object.
> - For each type category (elementary type, table, and so on), there is a type description class (e.g. `CL_ABAP_STRUCTDESCR` for structures, as shown in the hierarchy tree above) that has special attributes (i.e. the properties of the respective types).
> - References to type description objects can be used, for example, after the `TYPE HANDLE` addition of the `CREATE DATA` and `ASSIGN` statements.
The following examples show the retrieval of type information. Instead of the
cumbersome extra declaration of data reference variables, you can use
[inline declarations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm "Glossary Entry").
[Method chaining](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmethod_chaining_glosry.htm "Glossary Entry")
comes in handy, too.
```abap
"Getting a reference to a type description object of a type.
"i.e. getting an instance of a type description class.
"To do so, the static methods of the class CL_ABAP_TYPEDESCR can be used.
"As shown below, the type decription object can be used to create data
"objects dynamically. Note that instances of classes are not covered.
"Type for which information should be retrieved
TYPES elem_type TYPE c LENGTH 5.
"Creating a data reference variable to hold the reference to
"the type description object
DATA type_descr_obj_elem TYPE REF TO cl_abap_elemdescr.
"Retrieving type information by creating an instance of a type description
"class. As the name implies, the describe_by_name method expects the name
"of the type. In the following example, the reference to the type object is
"assigned using a downcast to the reference variable of type CL_ABAP_ELEMDESCR
"created above.
type_descr_obj_elem = CAST #( cl_abap_typedescr=>describe_by_name( 'ELEM_TYPE' ) ).
"Using the older cast operator ?=
type_descr_obj_elem ?= cl_abap_typedescr=>describe_by_name( 'ELEM_TYPE' ).
"Inline declaration is handy to avoid helper variables.
DATA(type_descr_obj_inl_1) = CAST cl_abap_elemdescr(
cl_abap_typedescr=>describe_by_name( 'ELEM_TYPE' ) ).
"You may want to check the type description object in the debugger.
"Various methods/attributes provide you with detailed information.
"The following examples show a selection:
"Kind/Type kind/Output length
DATA(kind) = type_descr_obj_inl_1->kind. "E (elementary)
DATA(type_kind) = type_descr_obj_inl_1->type_kind. "C
DATA(output_length) = type_descr_obj_inl_1->output_length. "5
"In the following example, the type properties are retrieved
"without casting. The data object has the type ref to
"cl_abap_typedescr. See the hierarchy tree above.
"The reference in the type description object references an
"object from one of the classes CL_ABAP_ELEMDESCR, CL_ABAP_ENUMDESCR,
"CL_ABAP_REFDESCR, CL_ABAP_STRUCTDESCR, CL_ABAP_TABLEDSECR,
"CL_ABAP_CLASSDESCR, or CL_ABAP_INTFDESCR.
"In the following case, it is CL_ABAP_ELEMDESCR.
"Note that in most of the following examples, the explicit
"casting is included when retrieving a reference to the type
"description object.
TYPES another_elem_type TYPE n LENGTH 3.
DATA(type_descr_obj_inl_2) = cl_abap_typedescr=>describe_by_name( 'ANOTHER_ELEM_TYPE' ).
"More types
"Structured data type (here, using the name of a database table)
DATA(type_descr_obj_struc) = CAST cl_abap_structdescr(
cl_abap_typedescr=>describe_by_name( 'ZDEMO_ABAP_CARR' ) ).
"Various attributes/methods available for detailed information
"Kind
DATA(struc_kind) = type_descr_obj_struc->kind. "S
"Getting components of the structure (e.g. the component names
"and type description objects for the individual components)
DATA(comps_struc) = type_descr_obj_struc->get_components( ).
"The follwing attribute also lists the component names and types
"(but not the type desription objects as is the case above)
DATA(comps_struc2) = type_descr_obj_struc->components.
"Kind of structure
DATA(struct_kind) = type_descr_obj_struc->struct_kind. "F (flat)
"Internal table type
TYPES tab_type TYPE SORTED TABLE OF zdemo_abap_carr
WITH UNIQUE KEY carrid.
DATA(type_descr_obj_tab) = CAST cl_abap_tabledescr(
cl_abap_typedescr=>describe_by_name( 'TAB_TYPE' ) ).
"Kind
DATA(tab_kind) = type_descr_obj_tab->kind. "T
"The following method returns more information than the attribute
"below (e.g. key kind, i.e. if it is a unique key, etc.)
DATA(tab_keys) = type_descr_obj_tab->get_keys( ).
DATA(tab_keys2) = type_descr_obj_tab->key.
"Getting internal table components
"The method get_table_line_type returns a variable of type ref to
"cl_abap_datadescr. This way you can retrieve the table components.
"Method chaining is useful here.
DATA(tab_comps) = CAST cl_abap_structdescr(
type_descr_obj_tab->get_table_line_type( ) )->get_components( ).
"Reference type
TYPES ref_str TYPE REF TO string.
DATA(type_descr_obj_ref) = CAST cl_abap_refdescr(
cl_abap_typedescr=>describe_by_name( 'REF_STR' ) ).
"Returns the type description object of the referenced type
DATA(ref_type) = type_descr_obj_ref->get_referenced_type( ).
"Getting the absolute type name
DATA(ref_type_abs_name) =
type_descr_obj_ref->get_referenced_type( )->absolute_name. "\TYPE=STRING
"Kind/Type kind
DATA(ref_kind) = type_descr_obj_ref->kind. "R
DATA(ref_type_type_kind) =
type_descr_obj_ref->get_referenced_type( )->type_kind. "g (string)
"Getting a reference to a type description object of an existing
"data object. Instead of referring to the name of a type, referring
"to a data object here. The relevant method is describe_by_data.
"Elementary data object
DATA dobj_elem type i.
DATA(ty_des_obj_el) = CAST cl_abap_elemdescr(
cl_abap_typedescr=>describe_by_data( dobj_elem ) ).
"Structure
DATA dobj_struc type zdemo_abap_carr.
DATA(ty_des_obj_struc) = CAST cl_abap_structdescr(
cl_abap_typedescr=>describe_by_data( dobj_struc ) ).
"Internal table
DATA dobj_itab type table of zdemo_abap_carr with empty key.
DATA(ty_des_obj_itab) = CAST cl_abap_tabledescr(
cl_abap_typedescr=>describe_by_data( dobj_itab ) ).
"Reference variable
DATA dref_var type ref to string.
DATA(ty_des_obj_dref) = CAST cl_abap_refdescr(
cl_abap_typedescr=>describe_by_data( dref_var ) ).
```
Excursions:
```abap
"Casting and method chaining as above in contrast to the following
"extra declarations. If the variables were not declared inline as
"in the example, there would be even more lines of code.
DATA(a) = cl_abap_typedescr=>describe_by_data( some_struc ).
DATA(b) = CAST cl_abap_structdescr( a ).
DATA(c) = b->components.
"As mentioned earlier about type name specifications for statements
"such as CREATE DATA, in addition to character-like data objects for
"the type name specified in the parentheses, you can also use absolute
"type names.
"Type to refer to
TYPES type4abs TYPE p LENGTH 4 DECIMALS 3.
"Data and object reference variables with generic types
DATA dref4abs TYPE REF TO data.
DATA oref4abs TYPE REF TO object.
"Getting absolute names
DATA(abs_name_type) = cl_abap_typedescr=>describe_by_name(
'TYPE4ABS' )->absolute_name.
DATA(abs_name_cl) = cl_abap_typedescr=>describe_by_name(
'ZCL_DEMO_ABAP_DYNAMIC_PROG' )->absolute_name.
"Data references
"Named data object holding the absolute name
CREATE DATA dref4abs TYPE (abs_name_type).
"Unnamed data object
CREATE DATA dref4abs TYPE ('\TYPE=STRING').
"Object references
"Named data object
CREATE OBJECT oref4abs TYPE (abs_name_cl).
"Unnamed data object
CREATE OBJECT oref4abs TYPE ('\CLASS=ZCL_DEMO_ABAP_DYNAMIC_PROG').
```
⬆️ back to top
### Dynamically Creating Data Types at Runtime
You can create data types at program runtime using methods of the type description classes of RTTS.
These types are only valid locally in the program. They are also anonymous, i.e. they are only accessible through type description objects.
As shown above, you can get a reference to a type description object of a type using the static methods of the class `CL_ABAP_TYPEDESCR`.
```abap
"For example, a structured type
DATA(type_descr_obj) = CAST cl_abap_structdescr(
cl_abap_typedescr=>describe_by_name( 'SOME_STRUC_TYPE' ) ).
```
The focus here is on using RTTC methods such as `get...`.
```abap
"Creating type description objects using ...
"... elementary data types
"Conceptually, all elementary, built-in ABAP types already
"exist and can be accessed by the corresponding get_* methods.
"In ADT, click CTRL + space after cl_abap_elemdescr=>...
"to check out the options. The following examples show a
"selection.
DATA(tdo_elem_i) = cl_abap_elemdescr=>get_i( ).
DATA(tdo_elem_string) = cl_abap_elemdescr=>get_string( ).
"For the length specification of type c and others, there is
"an importing parameter available.
DATA(tdo_elem_c_l20) = cl_abap_elemdescr=>get_c( 10 ).
"Type p with two parameters to be specified.
DATA(tdo_elem_p) = cl_abap_elemdescr=>get_p( p_length = 3
p_decimals = 2 ).
"Note: Instead of calling get_i() and others having no importing
"parameters, you could also call the describe_by_name( ) method
"and pass the type names (I‚ STRING etc.) as arguments.
"DATA(tdo_elem_i_2) = CAST cl_abap_elemdescr(
" cl_abap_typedescr=>describe_by_name( 'I' ) ).
"DATA(tdo_elem_string_2) = CAST cl_abap_elemdescr(
" cl_abap_typedescr=>describe_by_name( 'STRING' ) ).
"... structured data types
"They are created based on a component description table.
"A structured type such as the following shall be created dynamically
"using a type description object.
TYPES: BEGIN OF struc_type,
a TYPE string,
b TYPE i,
c TYPE c LENGTH 5,
d TYPE p LENGTH 4 DECIMALS 3,
END OF struc_type.
"Creating a type description object using RTTC method
"Using the get method, you can create the type description object
"dynamically based on a component table. The component table is
"of type abap_component_tab. In this example, the component table
"is created inline.
DATA(tdo_struc) = cl_abap_structdescr=>get(
VALUE #(
( name = 'A' type = cl_abap_elemdescr=>get_string( ) )
( name = 'B' type = cl_abap_elemdescr=>get_i( ) )
( name = 'C' type = cl_abap_elemdescr=>get_c( 5 ) )
( name = 'D' type = cl_abap_elemdescr=>get_p( p_length = 4
p_decimals = 3 ) ) ) ).
"... internal table types
"Note: Specifying the line type is mandatory, the rest is optional.
"An internal table type such as the following shall be created dynamically
"using a type description object.
TYPES std_tab_type_std_key TYPE STANDARD TABLE OF string
WITH DEFAULT KEY.
"Creating a type description object using RTTC method
"Not specifying the other optional parameters means that the
"default values are used, for example, standard table is the
"default value for p_table_kind.
DATA(tdo_tab_1) = cl_abap_tabledescr=>get(
p_line_type = cl_abap_elemdescr=>get_string( ) ).
"Another internal table type for which more parameter specifications
"are needed. The following internal table type shall be created using
"a type description object.
TYPES so_table_type TYPE SORTED TABLE OF zdemo_abap_flsch
WITH UNIQUE KEY carrid connid.
"Creating a type description object using RTTC method
"The following example also demonstrates how comfortably constructor
"operators can be used at these positions.
DATA(tdo_tab_2) = cl_abap_tabledescr=>get(
p_line_type = CAST cl_abap_structdescr(
cl_abap_tabledescr=>describe_by_name( 'ZDEMO_ABAP_FLSCH' ) )
p_table_kind = cl_abap_tabledescr=>tablekind_sorted
p_key = VALUE #( ( name = 'CARRID' ) ( name = 'CONNID' ) )
p_unique = cl_abap_typedescr=>true ).
" ... reference types
"Reference types such as the following shall be created using a
"type description object.
TYPES some_ref_type2t TYPE REF TO t.
TYPES some_ref_type2cl TYPE REF TO zcl_demo_abap_dynamic_prog.
"Using RTTC methods
"You can create a reference type from a base type. This base type
"may be class, interface or data type.
DATA(tdo_ref_1) = cl_abap_refdescr=>get( cl_abap_elemdescr=>get_t( ) ).
DATA(tdo_ref_2) = cl_abap_refdescr=>get(
cl_abap_typedescr=>describe_by_name( 'ZCL_DEMO_ABAP_DYNAMIC_PROG' ) ).
"Alternative: get_by_name method
DATA(tdo_ref_3) = cl_abap_refdescr=>get_by_name( 'T' ).
DATA(tdo_ref_4) = cl_abap_refdescr=>get_by_name( 'ZCL_DEMO_ABAP_DYNAMIC_PROG' ).
```
⬆️ back to top
### Dynamically Creating Data Objects at Runtime
As shown above, anonymous data objects can be dynamically created using `CREATE DATA` statements in many ways by specifying the type ...
- statically: `CREATE DATA dref TYPE string.`
- dynamically: `CREATE DATA dref TYPE (some_type).`
Another way to dynamically create data objects with dynamic type specification is to use types created at runtime with RTTC methods.
The `CREATE DATA` statement provides the [`TYPE HANDLE`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcreate_data_handle.htm) addition after which you can specify type description objects. A reference variable of the static type of class `CL_ABAP_DATADESCR` or its subclasses that points to a type description object can be specified after `TYPE HANDLE`.
``` abap
DATA dref_cr TYPE REF TO data.
"Elementary data object
"Type description object for an elementary type
DATA(tdo_elem_c_l20) = cl_abap_elemdescr=>get_c( 10 ).
"Creating an elementary data object based on a type description object
CREATE DATA dref_cr TYPE HANDLE tdo_elem_c_l20.
"Structure
DATA(tdo_struc) = cl_abap_structdescr=>get(
VALUE #(
( name = 'COMP1' type = cl_abap_elemdescr=>get_string( ) )
( name = 'COMP2' type = cl_abap_elemdescr=>get_i( ) )
( name = 'COMP3' type = cl_abap_elemdescr=>get_c( 3 ) ) ) ).
"Creating a structure based on a type description object
CREATE DATA dref_cr TYPE HANDLE tdo_struc.
"Internal table
"In the case below, it is a standard table with standard key by
"default because the other parameters are not specified.
DATA(tdo_tab) = cl_abap_tabledescr=>get(
p_line_type = CAST cl_abap_structdescr(
cl_abap_tabledescr=>describe_by_name( 'ZDEMO_ABAP_CARR' ) ) ).
"Creating an internal table based on a type description object
CREATE DATA dref_cr TYPE HANDLE tdo_tab.
"Data reference
DATA(tdo_ref) = cl_abap_refdescr=>get( cl_abap_elemdescr=>get_t( ) ).
CREATE DATA dref_cr TYPE HANDLE tdo_ref.
```
⬆️ back to top
## More Information
- It is recommended that you also consult section [Dynamic Programming Techniques (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynamic_prog_technique_gdl.htm) in the ABAP Keyword Documentation since it provides important aspects that should be considered when dealing with dynamic programming in general (e. g. security aspects or runtime error prevention).
- There are even further dynamic programming techniques in the unrestricted language scope such as the
generation or execution of programs at runtime. They are not part of this cheat sheet. Find more details on the related syntax (e. g. `GENERATE SUBROUTINE POOL`, `READ REPORT` and `INSERT REPORT` in the ABAP Keyword Documentation for Standard ABAP: [Dynamic Program Development (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_language_dynamic.htm)
## Executable Example
[zcl_demo_abap_dynamic_prog](./src/zcl_demo_abap_dynamic_prog.clas.abap)
Note the steps outlined [here](README.md#-getting-started-with-the-examples) about how to import and run the code.