Skip to Content

ABAP News for Release 7.40 – Constructor Operators CONV and CAST

With Release 7.40 ABAP supports so called constructor operators. Constructor operators are used in constructor expressions to create a result that can be used at operand positions. The syntax for constructor expressions is

… operator type( … ) …

operator is a constructor operator. type is either the explicit name of a data type or the character #. With # the data type can be dreived from the operand position if the operand type is statically known. Inside the parentheses specific parameters can be specified.

Conversion Operator CONV

The conversion operator CONV is a constructor operator that converts a value into the type specified in type.

… CONV dtype|#( … ) …

You use CONV  where you needed helper variables before in order to achieve a requested data type.

Example for parameter passing

Method cl_abap_codepage=>convert_to expects a string but you want to convert a text field.

Before release 7.40

DATA text TYPE c LENGTH 255.

DATA helper TYPE string.

DATA xstr   TYPE xstring.

helper = text.

xstr = cl_abap_codepage=>convert_to( source = helper ).

With release 7.40

DATA text TYPE c LENGTH 255.

DATA(xstr) = cl_abap_codepage=>convert_to( source = CONV string( text ) ).

In such cases it is even simpler to write

DATA text TYPE c LENGTH 255.

DATA(xstr) = cl_abap_codepage=>convert_to( source = CONV #( text ) ).

Example for influencing a calculation

IF 1 / 3 > 0.



is false, but

IF CONV decfloat34( 1 / 3 ) > 0.



is true!

Example for influencing a comparison

The infamous


IF ‘ ‘ = ` `.



is false. But

IF ‘ ‘ = CONV char1( ` ` ).



is true!

Casting Operator CAST

The casting operator CAST is a constructor operator that executes an up or down cast for reference varaibles with the type specified in type.

… CAST dtype|class|interface|#( … ) …

  • You use CAST for a down cast where you needed helper variables before in order to cast with ?= to a requested reference type.
  • You use CAST for an up cast, e,g, with an inline declaration, in order to construct a more general type.

You can write a compnent selector -> directly behind CAST type( … ).


Example from RTTI

Common example where a down cast is needed.

Before release 7.40

DATA structdescr TYPE REF TO cl_abap_structdescr.
structdescr ?= cl_abap_typedescr=>describe_by_name( ‘T100’ ).

DATA components  TYPE abap_compdescr_tab.

components = structdescr->components.

With release 7.40


DATA(components) = CAST cl_abap_structdescr(

  cl_abap_typedescr=>describe_by_name( ‘T100’ ) )->components.

Example with up cast

The static type of the reference variable iref declared inline should be the interface not the class.


    CLASS-METHODS factory RETURNING value(ref) TYPE REF TO cl.

  METHOD factory.
    ref = NEW #( ).

  DATA(iref) = CAST if( cl=>factory( ) ).

Example with data objects

A constructor expression with CAST followed by -> is an LHS-expression, you can assign values to it.

TYPES: BEGIN OF t_struc,
        col1 TYPE i,
        col2 TYPE i,
       END OF t_struc.

DATA dref  TYPE REF TO data.
DATA struc TYPE t_struc.

dref = NEW t_struc( ).

CAST t_struc( dref )->col1 = struccol1.

You must be Logged on to comment or reply to a post.
    • I can ask the developers about that.

      For the time being I myself also work like you have described it in your blog (using CAST from 7.40 on).

          CAST class( oref ).
        CATCH cx_sy_move_cast_error.

      • Tbh i was coding a (super)class yesterday & share Volker's desperation for IS INSTANCE OF 😉 There is no simple way of doing this in ABAP, sigh 🙁

        Horst Keller - Judging by the looks of it, i can see the demise of helper variables. Btw one thing came to my mind (in fact i had this in the back of my mind for sometime now, basically since i started chaining my methods 🙂 )

        We have a functional method:

        go_animal=>get_instance->get_no_of_legs( )

        Suppose i have to call this method multiple times in my method (for some weird reason), what do we suggest we should do -

        1. Call this chained statement everytime, or
        2. Declare a helper variable & use it?



          1. Call this chained statement everytime, or
          2. Declare a helper variable & use it?

          The recommendation is absolutely clear for such cases:

          2. Declare a helper variable & use it

          Unfortunately the compiler does not recognize and buffer such intermediate results.

          Use expressions to:

          • make source code better readable
          • but avoid
            • obfuscation
            • performance leaks
            • less maintainability (also for debugging it can be wise to awitch in one or the other helper variable)
      • PS: The correct answer of thread Object problem can be rewritten as follows in release 7.40:

        DATA oref TYPE REF TO object.

        oref = NEW some_class( ).

        IF CAST cl_abap_classdescr(
             cl_abap_typedescr=>describe_by_name( 'some_class' )
               )->applies_to( oref ) = 'X'.

        At least one expression without helper variables ...

      • Does that mean that just because some people don't know how to use a language construct it's not going to be implemented? I can think of tons of ways to create bad examples for all the additions you blogged about. In contrast, there are valid uses of an 'instance of' operator - "if the class has implemented an interface to support some special handling, call the method of that interface, else use a generic method". You don't always have the option of changing the inheritance structure unless your language supports multiple inheritance - which C++ does, but neither Java nor ABAP do. So that's not much of an answer, to be honest.

        • Well, it's the opinion of the colleagues who design and implement all that stuff. I myself have use cases for INSTANCE OF too (especially in connection with RTTI) and I also use

          class( oref ).
          CATCH cx_sy_move_cast_error.


  • IF CONV decfloat34( 1 / 3 ) > 0.



    is true!

    I would have expected that the integer division happens first and the resulting integer zero is then converted to float.

    I guess my expectation is even more evident if I add some brackets:

    data(a) = conv decfloat34( ( 1 / 3 ) ).

    But a will be 0.33333..

    Could you explain this behavior to me please?

    • Hi Bernhard,

      In ABAP, arithmetic calculations have a calculation type that is derived not only from the operands at the RHS but also from the result type (LHS). The result type in your case is decfloat34 and therefore, the calculation is carried out in decfloat34.

      See also Calculation Type, where the observed behavior is explained.

  • Thanks for the infos.

    Do you know how to get the CONV to work with a CHANGING parameter?

    the example here

    ABAP Keyword Documentation

    works for importing but not changing

    e.g. I cannot activate the * commented lines below - see Syntax-Error


    class lcl_conv1 definition.
       public section.
         types tt_sta
           type standard table of scarr with key mandt carrid.
         methods import
             !II type LCL_CONV1=>TT_STA
             !CI type LCL_CONV1=>TT_STA optional
       private section.
         methods test.
    endclass. " lcl_conv1 definition.
    class lcl_conv1 implementation.
       method IMPORT.
       endmethod. " IMPORT.
       method TEST.
         data li type sorted table of scarr with unique key mandt carrid.
         me->IMPORT( conv #( li ) ).
         me->IMPORT( exporting II = conv #( li ) ).
    *    me->IMPORT(
    *      exporting
    *        II = conv #( li )
    *      changing
    *        CI = conv #( li ) "Syntax-Error: Unexpected operator "CONV"
    *    ).
       endmethod. " TEST.
    endclass. " lcl_conv1 implementation.



    • Let me play the senior teacher here: 😈

      How do you think could any expression work as an actual parameter for CHANGING?

      Hint: Why can't you use expressions for EXPORTING/RETURNING parameters or use them as target fields of any assignments?

      • Actually, I'm whining about having to always copy my internal tables to a standard table just to display them, because salv takes a standard table only;- so I thought CONV would be a relief for that:


        class lcl_conv2 definition.
           public section.
             types tt_sta
               type standard table of scarr with key mandt carrid.
             methods show
                 !CI type LCL_CONV2=>TT_STA
             methods test.
        endclass. " lcl_conv2 definition.
        class lcl_conv2 implementation.
           method show.
             data lo type ref to CL_SALV_TABLE.
                 R_SALV_TABLE = lo
                 t_table      = CI
             lo->DISPLAY( ).
           endmethod. " show.
           method TEST.
             data li type sorted table of scarr with unique key mandt carrid.
             data li_helper type LCL_CONV2=>TT_STA.

             select * from scarr into table li.
             li_helper = li.
             me->SHOW( changing CI = li_helper ).
        endclass. " lcl_conv2 implementation.

        • Well, you can never write to an expression (with some exceptions).

          An expression returns a temporary result that can be used at the operand position, but not further. An actual parameter for CHANGING clearly is a write position. The changed parameter cannot be returned to the expression. You wouldn't write meth( CHANGING para = a + b ) either.  Only some expressions are wirtable expressions: variants of NEW, CAST, and table expressions. Those can be used at some few write positions, but not with CHANGING.

          Therefore, your problem cannot be solved by the compiler. I myself did never understand why the SALV classes do not accept any table type and why it is a CHANGING and not an IMPORTING parameter. But these classes are not  part of ABAP language,.

          • yes yes yes.

            I was hoping CONV would do something it doesn't.

            I fully understand your point on Expressions,

            Thanks much for your insights.

            I guess I have an explanation for your "question" on SALV:

            Class CL_SALV_TABLE has its method "FACTORY" with changing parameter t_table typed as "TYPE TABLE";

            (i.e. standard table)

            it then passes this to method "r_salv_table->set_data()" via parameter t_table typed as "TYPE STANDARD TABLE";

            this method contains: "get reference of t_table into me->r_table"

            where "me->r_table" is typed "Type Ref To DATA"

            Class CL_GUI_ALV_GRID has its method "SET_TABLE_FOR_FIRST_DISPLAY"

            with parameter IT_OUTTAB typed as "TYPE STANDARD TABLE";

            and this method does a "get reference of it_outtab into mt_outtab."

            where mt_outtab is typed "Type Ref To DATA"

            So these both eventually pass into variables that would take any table.

            BUT, checking for usage of e.g. the ladder mt_outtab, this gives e.g.:

            Class CL_GUI_ALV_GRID with method "APPLY_FILTER":

            This method contains: "assign mt_outtab->* to <tab1>." where <tab1> is typed "type standard table."

            This calls function module "LVC_FILTER_APPLY" which has parameter tables "it_data" which is typed "TABLE"

            (i.e. standard table)

            and so on...

            So this would required re-typing all these and more usages.

            But there is more:

            Hashed tables do not administrate sy-tabix within a Loop.

            e.g. look at: "form filt_conv_fcat_to_lvcfilter"

            in function group: SLVC_DIALOG

            (include = LSLVC_DIALOGF18)

            It contains:


                loop at t_data[] into t_data.

                  if sy-tabix = 1.


            where t_data is "tables t_data type table"

            Now, if t_date was "any table", and then if we pass a hashed table, then sy-tabix would always be 0.

            Like for example here:

            sy-tabix is 0 (it's not a bug, it's a feature?)


            form z_hashed_sy_tabix.

              data li type hashed table of scarr with unique key mandt carrid.

              data li2 type sorted table of scarr with unique key mandt carrid.

              field-symbols <lfs> like line of li.

              select * from scarr into table li.

              sort li by mandt carrid.

              sy-tabix = -1.

              LOOP at li assigning <lfs>.

                write: /'sy-tabix=', (2) sy-tabix, <lfs>-CARRID.


            endform. " z_hashed_sy_tabix.


            So "sy-tabix = 1" cannot be used to find the first line with a hashed table.

            Yet, even if the typing was merely changed to "index table",

            that would allow for standard AND sorted tables.


            As things are, I'll keep copying my tables;

            at least this does NOT copy the body of the tables, because copy-on-write happens (I guess)


            So "only" a table header needs to be created (?)

        • Hi Armin,

          for me this is a good example of unreadable code.

          data li

          data li2

          field-symbols <lfs> like line of li.

          If you do not use meaningful names for IDs here, where do you?



  • Great work! Nice features!

    Where will I find these articles the day my customer uses 740? If I understand right, some of the features have been introduced with different service packs of 740. Is there an overview for this?

    Thank you, I enjoy reading the articles and the discussion - really encouraging!

    And: "Beauty Is Not in the Eye of the Beholder. Beauty Is All Around Us, Contained in Nature!"

  • Seems, that CONV does not work in CONCATENATE:

    data: stringfield type string.

    concatenate conv string( sy-tabix ) 'anythingelse' into stringfield.

    Could you tell me, why?

  • Hi Horst,

    given following example of the CAST operator:

    TYPES t_c_big TYPE c LENGTH 262143.
    DATA lv_char1 TYPE char1 VALUE '@'.
    DATA lr_data_1 TYPE REF TO data.
    GET REFERENCE OF lv_char1 INTO lr_data_1.
    DATA(lr_data_2) = CAST t_c_big( lr_data_1 ).

    Why do I get access to foreign memory in LR_DATA_2 after the first character? Is this a bug in the CAST operator?

    I would have expected an exception due to some kind of memory check.

    Kernel: 742 PL#200

    Thank you in advance!

    Best regards,


    • Now, that doesn't look good 😯 .

      According to the documentation the down cast should not be possible but lead to an exception CX_SY_MOVE_CAST_ERROR.

      It is not the CAST operator alone, but also the ?= operator behaves wrongly:

      DATA lr_data_3 TYPE REF TO t_c_big.
      lr_data_3 ?= lr_data_1.

      I tested in 7.40, SP08 and 7.50 and as you said, there is no exception and after assigning to a field symbol there is access to memory outside the allowed limits.

      Only in our internal 7.63 system I get at least a runtime error CAST_INTERNAL_ERROR, which also shouldn't occur, but of course the CX_SY_MOVE_CAST_ERROR.

      I forward to development. Thanks for notifying!

  • Hello Horst,

    dereferencing a CASTed object attribute seems to add an implicit conversion, or what is happening here?

    REPORT zz_cast_issue.
    * Tested on Netweaver 7.51
    TYPES tv_real TYPE decfloat34.  " real data type
    CLASS lcl_real DEFINITION.
        METHODS constructor IMPORTING iv_real TYPE tv_real.
        METHODS to_string RETURNING VALUE(rv_str) TYPE string.
        DATA real TYPE tv_real.
      METHOD constructor.
        real = iv_real.
      METHOD to_string.
        DATA lo_real TYPE REF TO lcl_real.
    *    rv_str = condense( real ).  " <--- Error - real must be a character-like data object (expected)
        rv_str = condense( CAST lcl_real( me )->real ). " works (not expected) ??
      WRITE NEW lcl_real( '2.423' )->to_string( ).



    To make a long thing short:

    DATA(str1) = condense( CONV decfloat34( '1' ) ).
    DATA decf TYPE decfloat34.
    DATA(str2) = condense( decf ). "Syntax error

    One of the many peculiarities of our good ol' ABAP language.

    As a data object, the operand must be character like (character-like data types or date types and time types, structures with flat-only character-like components),

    As an expression it is enough to be convertible.