This commit is contained in:
danrega
2024-02-05 16:23:01 +01:00
parent 1b2238f2b6
commit 5c070915fa

View File

@@ -1736,137 +1736,208 @@ The following examples show the retrieval of type information. Instead of the ex
comes in handy, too. comes in handy, too.
```abap ```abap
"Getting a reference to a type description object of a type. "------------------------------------------------------------------------
"i.e. getting an instance of a type description class. "---------------- Getting general type information ----------------------
"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 "Getting references to type description objects of a type ...
TYPES elem_type TYPE c LENGTH 5.
"... using the cl_abap_typedescr=>describe_by_name method.
"In this case, the name of the types are used.
"The following examples cover elementary, structured and
"internal table types.
TYPES elemtype TYPE n LENGTH 3.
TYPES structype TYPE zdemo_abap_carr.
TYPES strtabtype TYPE string_table.
"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_TABLEDESCR,
"CL_ABAP_CLASSDESCR, or CL_ABAP_INTFDESCR. You may want to check the
"content of the type description objects in the debugger.
DATA(tdo_by_name_elem) = cl_abap_typedescr=>describe_by_name( 'ELEMTYPE' ).
DATA(tdo_by_name_struc) = cl_abap_typedescr=>describe_by_name( 'STRUCTYPE' ).
DATA(tdo_by_name_itab) = cl_abap_typedescr=>describe_by_name( 'STRTABTYPE' ).
"Inline declarations are handy to avoid helper variables such as
"in the following example.
DATA tdo_by_name_elem_helper TYPE REF TO cl_abap_typedescr.
tdo_by_name_elem_helper = cl_abap_typedescr=>describe_by_name( 'ELEMTYPE' ).
"... using the cl_abap_typedescr=>describe_by_data method.
"In this case, the data objects are provided.
"The examples cover an elementary data object, a structure and and
"internal table.
DATA elemdobj TYPE elemtype.
DATA strucdobj TYPE structype.
DATA tabledobj TYPE strtabtype.
DATA(tdo_by_data_elem) = cl_abap_typedescr=>describe_by_data( 'ELEMTYPE' ).
DATA(tdo_by_data_struc) = cl_abap_typedescr=>describe_by_data( 'STRUCTYPE' ).
DATA(tdo_by_data_itab) = cl_abap_typedescr=>describe_by_data( 'STRTABTYPE' ).
"... using the cl_abap_typedescr=>describe_by_data_ref method
"In this case, a data reference variable is used.
"Note: As a result, the method returns a reference that points to
"an object in one of the classes CL_ABAP_ELEMDESCR, CL_ABAP_ENUMDESCR,
"CL_ABAP_REFDESCR, CL_ABAP_STRUCTDESCR, or CL_ABAP_TABLEDSECR.
DATA dref1 TYPE REF TO i.
dref1 = NEW #( ).
"Data reference pointing to CL_ABAP_ELEMDESCR
DATA(tdo_by_dref1) = cl_abap_typedescr=>describe_by_data_ref( dref1 ).
"Data reference pointing to CL_ABAP_TABLEDSECR
DATA(dref2) = NEW string_table( ).
DATA(tdo_by_dref2) = cl_abap_typedescr=>describe_by_data_ref( dref2 ).
"... using the cl_abap_typedescr=>describe_by_data_ref method
"In this case, an object reference variable is used.
DATA oref TYPE REF TO zcl_demo_abap_objects.
oref = NEW #( ).
DATA(tdo_by_oref) = cl_abap_typedescr=>describe_by_object_ref( oref ).
"------------------------------------------------------------------------
"--- Getting more detailed information by programmatically accessing ----
"--- the attributes -----------------------------------------------------
"------------------------------------------------------------------------
"------------------------------------------------------------------------
"--- Examples using a type description object for an elementary type ----
"------------------------------------------------------------------------
DATA(elem_kind) = tdo_by_name_elem->kind. "E (elementary)
DATA(elem_absolute_name) = tdo_by_name_elem->absolute_name. "Check in the debugger for such a local type
DATA(elem_relative_name) = tdo_by_name_elem->get_relative_name( ). "ELEMTYPE
DATA(elem_is_ddic_type) = tdo_by_name_elem->is_ddic_type( ). "has the value abap_false
"Getting more information using type-specific type description classes (e.g. cl_abap_elemdescr for elementary
"types, as shown in the hierarchy tree above)
"Using casts, you can access special attributes (i.e. the properties of the respective types).
"Creating a data reference variable to hold the reference to "Creating a data reference variable to hold the reference to
"the type description object "the type description object
DATA type_descr_obj_elem TYPE REF TO cl_abap_elemdescr. DATA ref_elemdescr TYPE REF TO cl_abap_elemdescr.
ref_elemdescr = CAST #( tdo_by_name_elem ).
"Using the older cast operator ?= (which is not used in the examples)
ref_elemdescr ?= tdo_by_name_elem.
"Retrieving type information by creating an instance of a type description "Alternatives using inline declaration
"class. As the name implies, the describe_by_name method expects the name DATA(ref_elemdescr2) = CAST cl_abap_elemdescr( tdo_by_name_elem ).
"of the type. In the following example, the reference to the type object is "Using method chaining, you can omit extra declarations
"assigned using a downcast to the reference variable of type CL_ABAP_ELEMDESCR DATA(ref_elemdescr3) = CAST cl_abap_elemdescr( cl_abap_typedescr=>describe_by_name( 'ELEMTYPE' ) ).
"created above. DATA(elem_abs_name) = CAST cl_abap_elemdescr( cl_abap_typedescr=>describe_by_name( 'ELEMTYPE' ) )->absolute_name.
type_descr_obj_elem = CAST #( cl_abap_typedescr=>describe_by_name( 'ELEM_TYPE' ) ). "Implementing a check before the cast to the type-specific type description class
IF tdo_by_name_elem IS INSTANCE OF cl_abap_elemdescr.
DATA(ref_elemdescr4) = CAST cl_abap_elemdescr( tdo_by_name_elem ).
ENDIF.
"Using the older cast operator ?= "Some examples for more detailed information that is accessible after
type_descr_obj_elem ?= cl_abap_typedescr=>describe_by_name( 'ELEM_TYPE' ). "the cast. Check the options after the object component selector ->.
DATA(elem_output_length) = ref_elemdescr->output_length. "3
"The following method checks compatibility of a specified data object
DATA(elem_applies1) = ref_elemdescr->applies_to_data( elemdobj ). "has the value abap_true
DATA test_dobj TYPE c LENGTH 3.
DATA(elem_applies2) = ref_elemdescr->applies_to_data( test_dobj ). "has the value abap_false
"Inline declarations are handy to avoid helper variables. "-----------------------------------------------------------------
DATA(type_descr_obj_inl_1) = CAST cl_abap_elemdescr( "--- Examples using a type description object for a structure ----
cl_abap_typedescr=>describe_by_name( 'ELEM_TYPE' ) ). "-----------------------------------------------------------------
DATA ref_structdescr1 TYPE REF TO cl_abap_structdescr.
ref_structdescr1 = CAST #( tdo_by_name_struc ).
"You may want to check the type description object in the debugger. "Check examples before making the cast
"Various methods/attributes provide you with detailed information. "The examples also use inline declaration.
"The following examples show a selection: CASE TYPE OF tdo_by_name_struc.
"Kind/Type kind/Output length WHEN TYPE cl_abap_structdescr.
DATA(kind) = type_descr_obj_inl_1->kind. "E (elementary) DATA(ref_structdescr2) = CAST cl_abap_structdescr( tdo_by_name_struc ).
DATA(type_kind) = type_descr_obj_inl_1->type_kind. "C WHEN OTHERS.
DATA(output_length) = type_descr_obj_inl_1->output_length. "5 ...
ENDCASE.
"In the following example, the type properties are retrieved DATA(ref_structdescr3) = COND #( WHEN tdo_by_name_struc IS INSTANCE OF cl_abap_structdescr
"without cast. The data object has the type ref to THEN CAST cl_abap_structdescr( tdo_by_name_struc ) ).
"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
"cast 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 "More details accessible after the cast
"Structured data type (here, using the name of a database table) DATA(struc_kind) = ref_structdescr1->struct_kind. "F (flat)
DATA(type_descr_obj_struc) = CAST cl_abap_structdescr( "The following attribute returns a table with component information, such as
cl_abap_typedescr=>describe_by_name( 'ZDEMO_ABAP_CARR' ) ). "the component names and type kinds.
DATA(struc_components) = ref_structdescr1->components.
"The following method also returns a table with component information. In this case,
"more information is returned such as type description objects of each component and more.
DATA(struc_components_tab) = ref_structdescr1->get_components( ).
"Various attributes/methods available for detailed information "-----------------------------------------------------------------------
"Kind "--- Examples using a type description object for an internal table ----
DATA(struc_kind) = type_descr_obj_struc->kind. "S "-----------------------------------------------------------------------
DATA ref_tabledescr1 TYPE REF TO cl_abap_tabledescr.
ref_tabledescr1 = CAST #( tdo_by_name_itab ).
"Cast with inline declaration (for a change)
DATA(ref_tabledescr2) = CAST cl_abap_tabledescr( tdo_by_name_itab ).
"Getting components of the structure (e.g. the component names "Another internal table as an example
"and type description objects for the individual components) DATA itab TYPE SORTED TABLE OF zdemo_abap_carr WITH UNIQUE KEY carrid.
DATA(comps_struc) = type_descr_obj_struc->get_components( ). DATA(ref_tabledescr3) = CAST cl_abap_tabledescr( cl_abap_typedescr=>describe_by_data( itab ) ).
"The follwing attribute also lists the component names and types DATA(itab_table_kind) = ref_tabledescr3->table_kind. "O (sorted table)
"(but not the type desription objects as is the case above) DATA(itab_has_unique_key) = ref_tabledescr3->has_unique_key. "has the value abap_true
DATA(comps_struc2) = type_descr_obj_struc->components. "Returns a table with the names internal table keys
DATA(itab_table_key) = ref_tabledescr3->key. "carrid
"Returns a table with a description of all table keys, e.g.
"all components of a key, key kind (U, unique, in the example case),
"information whether the key is the primary key etc.
DATA(itab_keys) = ref_tabledescr3->get_keys( ).
"If you want to get information about the line type, e.g. finding out about
"the component names, another cast is required.
"First, getting a reference to the type description object for the structured type.
DATA(itab_comp_ref) = ref_tabledescr3->get_table_line_type( ).
"Then, performing a cast to access the component information as shown above.
DATA(itab_line_info) = CAST cl_abap_structdescr( itab_comp_ref ).
DATA(itab_comps1) = itab_line_info->components.
DATA(itab_comps2) = itab_line_info->get_components( ).
"Kind of structure "----------------------------------------------------------------------
DATA(struct_kind) = type_descr_obj_struc->struct_kind. "F (flat) "--- Examples using a type description object for a data reference ----
"----------------------------------------------------------------------
DATA ref_refdescr1 TYPE REF TO cl_abap_refdescr.
TYPES type_ref_i TYPE REF TO i.
DATA(tdo_ref) = cl_abap_typedescr=>describe_by_name( 'TYPE_REF_I' ).
ref_refdescr1 = CAST #( tdo_ref ).
DATA(ref_refdescr2) = CAST cl_abap_refdescr( tdo_ref ).
"Internal table type "Getting a reference to the type description object of a type used to
TYPES tab_type TYPE SORTED TABLE OF zdemo_abap_carr "type the reference
WITH UNIQUE KEY carrid. DATA(ref_type) = ref_refdescr1->get_referenced_type( ).
DATA(ref_abs_name) = ref_refdescr1->get_referenced_type( )->absolute_name. "\TYPE=I
DATA(type_descr_obj_tab) = CAST cl_abap_tabledescr( "-------------------------------------------------------------------------
cl_abap_typedescr=>describe_by_name( 'TAB_TYPE' ) ). "--- Examples using a type description object for an object reference ----
"-------------------------------------------------------------------------
DATA ref_oref1 TYPE REF TO cl_abap_objectdescr.
ref_oref1 = CAST #( tdo_by_oref ).
"See the hierarchy of type description classes. You may also use
"cl_abap_classdescr.
DATA(ref_oref2) = CAST cl_abap_classdescr( tdo_by_oref ).
"Kind "Returns a table with information about the class attributes
DATA(tab_kind) = type_descr_obj_tab->kind. "T DATA(class_attributes) = ref_oref1->attributes.
"The following method returns more information than the attribute "Returns a table with information about the methods such as
"below (e.g. key kind, i.e. if it is a unique key, etc.) "parameters, visibility and more
DATA(tab_keys) = type_descr_obj_tab->get_keys( ). DATA(class_methods) = ref_oref1->methods.
DATA(tab_keys2) = type_descr_obj_tab->key.
"Getting internal table components "Returns a table with information about the interfaces implemented
"The method get_table_line_type returns a variable of type ref to DATA(class_intf) = ref_oref1->interfaces.
"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 "Can class be instantiated
TYPES ref_str TYPE REF TO string. DATA(class_is_inst) = ref_oref1->is_instantiatable( ). "has the value abap_true
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 "Using an interface
DATA(ref_type) = type_descr_obj_ref->get_referenced_type( ). DATA(tdo_intf) = cl_abap_typedescr=>describe_by_name( 'ZDEMO_ABAP_OBJECTS_INTERFACE' ).
DATA ref_iref TYPE REF TO cl_abap_intfdescr.
ref_iref = CAST #( tdo_intf ). "cl_abap_objectdescr is also possible
"Getting the absolute type name DATA(ref_intf_attr) = ref_iref->attributes.
DATA(ref_type_abs_name) = DATA(ref_intf_meth) = ref_iref->methods.
type_descr_obj_ref->get_referenced_type( )->absolute_name. "\TYPE=STRING DATA(ref_intf_attr_objdescr) = CAST cl_abap_objectdescr( tdo_intf )->attributes.
"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: Excursions:
@@ -1935,11 +2006,12 @@ DATA(type_descr_obj) = CAST cl_abap_structdescr(
cl_abap_typedescr=>describe_by_name( 'SOME_STRUC_TYPE' ) ). cl_abap_typedescr=>describe_by_name( 'SOME_STRUC_TYPE' ) ).
``` ```
The focus here is on using RTTC methods such as `get...`. The focus here is on using RTTC methods such as `get...`. It is recommended that you use the `get` method instead of the `create` method.
```abap ```abap
"Creating type description objects using ... "----------------------------------------------------------------------
"... elementary data types "--- Creating type description objects using elementary data types ----
"----------------------------------------------------------------------
"Conceptually, all elementary, built-in ABAP types already "Conceptually, all elementary, built-in ABAP types already
"exist and can be accessed by the corresponding get_* methods. "exist and can be accessed by the corresponding get_* methods.
"In ADT, click CTRL + space after cl_abap_elemdescr=>... "In ADT, click CTRL + space after cl_abap_elemdescr=>...
@@ -1965,7 +2037,9 @@ DATA(tdo_elem_p) = cl_abap_elemdescr=>get_p( p_length = 3
"DATA(tdo_elem_string_2) = CAST cl_abap_elemdescr( "DATA(tdo_elem_string_2) = CAST cl_abap_elemdescr(
" cl_abap_typedescr=>describe_by_name( 'STRING' ) ). " cl_abap_typedescr=>describe_by_name( 'STRING' ) ).
"... structured data types "----------------------------------------------------------------------
"--- Creating type description objects using structured data types ----
"----------------------------------------------------------------------
"They are created based on a component description table. "They are created based on a component description table.
"A structured type such as the following shall be created dynamically "A structured type such as the following shall be created dynamically
@@ -1990,13 +2064,14 @@ DATA(tdo_struc) = cl_abap_structdescr=>get(
( name = 'D' type = cl_abap_elemdescr=>get_p( p_length = 4 ( name = 'D' type = cl_abap_elemdescr=>get_p( p_length = 4
p_decimals = 3 ) ) ) ). p_decimals = 3 ) ) ) ).
"... internal table types "---------------------------------------------------------------------
"--- Creating type description objects using internal table types ----
"---------------------------------------------------------------------
"Note: Specifying the line type is mandatory, the rest is optional. "Note: Specifying the line type is mandatory, the rest is optional.
"An internal table type such as the following shall be created dynamically "An internal table type such as the following shall be created dynamically
"using a type description object. "using a type description object.
TYPES std_tab_type_std_key TYPE STANDARD TABLE OF string TYPES std_tab_type_std_key TYPE STANDARD TABLE OF string WITH DEFAULT KEY.
WITH DEFAULT KEY.
"Creating a type description object using RTTC method "Creating a type description object using RTTC method
"Not specifying the other optional parameters means that the "Not specifying the other optional parameters means that the
@@ -2008,8 +2083,7 @@ DATA(tdo_tab_1) = cl_abap_tabledescr=>get(
"Another internal table type for which more parameter specifications "Another internal table type for which more parameter specifications
"are needed. The following internal table type shall be created using "are needed. The following internal table type shall be created using
"a type description object. "a type description object.
TYPES so_table_type TYPE SORTED TABLE OF zdemo_abap_flsch TYPES so_table_type TYPE SORTED TABLE OF zdemo_abap_flsch WITH UNIQUE KEY carrid connid.
WITH UNIQUE KEY carrid connid.
"Creating a type description object using RTTC method "Creating a type description object using RTTC method
"The following example also demonstrates how comfortably constructor "The following example also demonstrates how comfortably constructor