Skip to content

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

Comments