CL_ABAP_TYPEDESCR¶
Runtime Type Information (RTTI) — inspect the type of any variable or object at runtime.
Purpose¶
The RTTI class hierarchy lets you examine types, structure layouts, class hierarchies, and method signatures at runtime. The entry points are static factory methods on CL_ABAP_TYPEDESCR.
Class hierarchy¶
CL_ABAP_TYPEDESCR
├── CL_ABAP_DATADESCR (data types)
│ ├── CL_ABAP_ELEMDESCR (elementary: I, STRING, D, ...)
│ ├── CL_ABAP_REFDESCR (reference types: REF TO ...)
│ ├── CL_ABAP_STRUCTDESCR (flat structures and deep structures)
│ └── CL_ABAP_TABLEDESCR (internal tables)
└── CL_ABAP_OBJECTDESCR (classes and interfaces)
├── CL_ABAP_CLASSDESCR
└── CL_ABAP_INTFDESCR
Key factory methods¶
| Method | Input | Returns |
|---|---|---|
DESCRIBE_BY_DATA( var ) |
Any variable | CL_ABAP_DATADESCR |
DESCRIBE_BY_NAME( 'TYPE_NAME' ) |
DDIC type name string | CL_ABAP_TYPEDESCR |
DESCRIBE_BY_OBJECT_REF( oref ) |
Object reference | CL_ABAP_OBJECTDESCR |
DESCRIBE_BY_DATA_REF( dref ) |
Data reference | CL_ABAP_DATADESCR |
Examples¶
Get the type name of a variable¶
REPORT z_rtti_type_name.
START-OF-SELECTION.
DATA lv_amount TYPE p DECIMALS 2.
lv_amount = '12345.67'.
DATA(lo_descr) = cl_abap_typedescr=>describe_by_data( lv_amount ).
WRITE: / 'Type kind:', lo_descr->type_kind. " 'P'
WRITE: / 'Type name:', lo_descr->get_relative_name( ).
Inspect structure components¶
REPORT z_rtti_components.
START-OF-SELECTION.
DATA ls_flight TYPE sflight.
DATA(lo_struct) = CAST cl_abap_structdescr(
cl_abap_typedescr=>describe_by_data( ls_flight ) ).
LOOP AT lo_struct->components INTO DATA(ls_comp).
WRITE: / ls_comp-name, ls_comp-type_kind, ls_comp-length.
ENDLOOP.
Check if object is instance of a specific class¶
REPORT z_rtti_instance.
START-OF-SELECTION.
DATA lo_salv TYPE REF TO cl_salv_table.
DATA lt_data TYPE STANDARD TABLE OF sflight.
SELECT * FROM sflight INTO TABLE @lt_data UP TO 3 ROWS.
cl_salv_table=>factory(
IMPORTING r_salv_table = lo_salv
CHANGING t_table = lt_data ).
" Get a column — may be CL_SALV_COLUMN_LIST or CL_SALV_COLUMN_TABLE
DATA(lo_col) = lo_salv->get_columns( )->get_column( 'CARRID' ).
" Use IS INSTANCE OF — safe, no dump risk
IF lo_col IS INSTANCE OF cl_salv_column_table.
DATA(lo_table_col) = CAST cl_salv_column_table( lo_col ).
WRITE: / 'Column is CL_SALV_COLUMN_TABLE'.
ELSE.
WRITE: / 'Column type:', cl_abap_typedescr=>describe_by_object_ref( lo_col )->get_relative_name( ).
ENDIF.
Get method list of a class by name¶
REPORT z_rtti_methods.
START-OF-SELECTION.
DATA(lo_class) = CAST cl_abap_classdescr(
cl_abap_typedescr=>describe_by_name( 'CL_SALV_TABLE' ) ).
LOOP AT lo_class->methods INTO DATA(ls_method).
WRITE: / ls_method-name.
ENDLOOP.
Validate a DDIC type before dynamic CREATE DATA¶
REPORT z_rtti_create_data.
START-OF-SELECTION.
DATA lv_type_name TYPE string VALUE 'BAPI_RETURN'.
DATA lo_data TYPE REF TO data.
DATA lo_type TYPE REF TO cl_abap_typedescr.
" describe_by_name raises a classical exception (not class-based)
" — use CALL METHOD with EXCEPTIONS, not TRY/CATCH
CALL METHOD cl_abap_typedescr=>describe_by_name
EXPORTING
p_name = lv_type_name
RECEIVING
p_descr_ref = lo_type
EXCEPTIONS
type_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE |Type { lv_type_name } not found in DDIC| TYPE 'E'.
RETURN.
ENDIF.
" Type is valid — safe to create dynamically
CREATE DATA lo_data TYPE (lv_type_name).
FIELD-SYMBOLS: <fs> TYPE any.
ASSIGN lo_data->* TO <fs>.
IF <fs> IS ASSIGNED.
WRITE: / 'Dynamic data created for type:', lv_type_name.
ENDIF.
Use IS INSTANCE OF instead of RTTI for simple class checks
lo_obj IS INSTANCE OF cl_my_class is faster and clearer than RTTI for simple type checks. Use RTTI when you need component lists, method signatures, or type metadata you can't express with IS INSTANCE OF.
See also¶
CX_SY_MOVE_CAST_ERROR— exception when CAST fails- Clean ABAP Quick Reference