Skip to Content
Author's profile photo Horst Keller

ABAP News for Release 7.50 – IS INSTANCE OF

This one is a tribute to the community, to SCN, to you. One of you, Volker Wegert; has blogged his ABAP Wishlist – IS INSTANCE OF some years ago and reminded us again and again. Others backed him and I myself participated a little bit by forwarding the wish to the kernel developers. And constant dripping wears the stone, ABAP 7.50 comes with a new relational expression IS INSTANCE OF, even literally.

 

If you wanted to find out whether a reference variable of a given static type can point to an object before ABAP 7.50, you had to TRY a casting operation that might look like something as follows:

    DATA(typedescr) = cl_abap_typedescr=>describe_by_data( param ).

    DATA:
      elemdescr   TYPE REF TO cl_abap_elemdescr,
      structdescr TYPE REF TO cl_abap_structdescr,
      tabledescr  TYPE REF TO cl_abap_tabledescr.
    TRY.
        elemdescr ?= typedescr.
        ...
      CATCH cx_sy_move_cast_error.
        TRY.
            structdescr ?= typedescr.
            ...
          CATCH cx_sy_move_cast_error.
            TRY.

                tabledescr ?= typedescr.
                ...
              CATCH cx_sy_move_cast_error.
                ...
            ENDTRY.
        ENDTRY.
    ENDTRY.


In this example we try to find the resulting type of an RTTI-operation.

 

With ABAP 7.50 you can do the same as follows:

 

    DATA(typedescr) = cl_abap_typedescr=>describe_by_data( param ).
    
    IF typedescr IS INSTANCE OF cl_abap_elemdescr.
      DATA(elemdescr) = CAST cl_abap_elemdescr( typedescr ).
      ...
    ELSEIF typedescr IS INSTANCE OF cl_abap_structdescr.
      DATA(structdescr) = CAST cl_abap_structdescr( typedescr ).
      ...
    ELSEIF typedescr IS INSTANCE OF cl_abap_tabledescr.
      DATA(tabledescr) = CAST cl_abap_tabledescr( typedescr ).
      ...
    ELSE.
      ...
    ENDIF.

The new predicate expression IS INSTANCE OF checks, if the dynamic type of the LHS operand is more special or equal to an RHS type. In fact it checks whether the operand can be down casted with that type. In the above example, such a casting takes place after IF, but its your decision if you need it. If you need it, there is even a shorter way to write it. A new variant of the CASE -WHEN construct:!

 

    DATA(typedescr) = cl_abap_typedescr=>describe_by_data( param ).

    CASE TYPE OF typedescr.
      WHEN TYPE cl_abap_elemdescr INTO DATA(elemdescr).
        ...
      WHEN TYPE cl_abap_structdescr INTO DATA(structdescr).
        ...
      WHEN TYPE cl_abap_tabledescr INTO DATA(tabledescr).
        ...
      WHEN OTHERS.
        ...
    ENDCASE.

The new TYPE OF and TYPE additions to CASE and WHEN allow you to write IS INSTANCE OF as a case control structure. The optional INTO addition does the casting for you, I think that’s rather cool.

 

B.T.W., the new IS INSTANCE OF and CASE TYPE OF even work for initial reference variables. Then they check if an up cast is possible.This can be helpful for checking the static types of formal parameters or field symbols that are typed generically. Therefore IS INSTANCE OF is not only instance of but might also be labeled as a type inspection operator.

 

For more information see:

 

Assigned tags

      35 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Volker Wegert
      Volker Wegert

      Horst,

      thank you very very much - this is excellent news. I like the new CASE syntax; it might take a little getting used to, but it should come in handy.

      (I won't spoil the party by asking when 7.50 will be available to "regular" customers - yet :-)).

        Volker

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      asking when 7.50 will be available to "regular" customers

      big pictures, big pictures ... 😉

      Author's profile photo Volker Wegert
      Volker Wegert

      Horst Keller wrote:

      big pictures, big pictures ... 😉

      big pictures = huge distances 🙁

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Same for me ...

      Deep inside can be as far as far outside 😐

      Author's profile photo Former Member
      Former Member

      I have been relegated to ABAP 700. Can't even use AiE 🙁

      Author's profile photo Peter Inotai
      Peter Inotai

      Hi Horst,

      It's really cool. We had a helper method for this, but this way it's much easier.

      Any downport planned for this (and generally for 7.50 features)?

      Thanks,

      Peter

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Any downport planned for this (and generally for 7.50 features)?

      Man, your'e killing me ... 😉

      But even I dare to say, that you might better not expect that.

      Author's profile photo Peter Inotai
      Peter Inotai

      Man, your'e killing me ... 😉

      No, I don't want to do that. That would be the biggest loss ever for the ABAP community 🙂


      But even I dare to say, that you might better not expect that.

      That's sad 🙁

      Author's profile photo Former Member
      Former Member

      Great news, Horst!

      It's so cool to see developers who listen to their community.

      From my perspective this would make RTII code so much nicer to read. Thumbs up!

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Another nice use case could be catching a general exception and finding the concrete exception with INSTANCE OF or CASE TYPE OF.

      Author's profile photo Raphael Pacheco
      Raphael Pacheco

      Great blog Horst!

      I liked this new way of making the casting. This 7.5 is making me very curious, I do not even have be delighted to use the ABAP 7.4 SP 8 and you already shows this beauty 7.5 🙁

      So... we have any news about the CDS too?


      Warm regards,


      Raphael Pacheco.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      So... we have any news about the CDS too?

      Yes ...

      Author's profile photo Peter Inotai
      Peter Inotai

      I'm sure there will be some blogs about them with more details. But if you can't wait, there are already some info here:

      ABAP Tools - What's New in SAP NetWeaver 7.5 (Release Notes) - SAP Library

      Author's profile photo Raphael Pacheco
      Raphael Pacheco

      Thanks Peter 😀

      Warm regards,

      Raphael Pacheco.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author
      Author's profile photo Raphael Pacheco
      Raphael Pacheco

      Wow! So fast 😯

      Thanks Horst !

      P.S.: Sorry for posting just now thanking the link.

      Author's profile photo Dirk Wittenberg
      Dirk Wittenberg

      Thanks for posting!

      Author's profile photo Matthew Billingham
      Matthew Billingham

      Ah, but is there a solution to Mike Pokraka's question Determine class name used for calling a static method?

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Isn't that a totally different question?

      I guess there is no simple solution. I expect that the ABAP runtime interprets the symbolic names ZCL_SUPER=> and ZCL_SUB=> in order to point to the method and forgets about it. Why should it keep the information? In fact I have a similar problem: Is there a simple way to find out the name of an actual parameter passed to a formal parameter inside a method? It isn't! I ended up in interpreting the call stack and parsing the calling code!

      Author's profile photo Christian Guenter
      Christian Guenter

      In fact I have a similar problem: Is there a simple way to find out the name of an actual parameter passed to a formal parameter inside a method?

      I'm curious, why do you want to know this?

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      DATA itab TYPE TABLE OF string.

      itab = value #( ( `a` ) ( `b` ) ).

      cl_demo_output=>display( itab ).

      I want "itab" as title for the output ...

      Author's profile photo Matthew Billingham
      Matthew Billingham

      "... I ended up in interpreting the call stack and parsing the calling code!" But all nicely encapsulated in like this, yes?

      if parameter->get_actual_parameter_name( ) ...

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      yes

      Author's profile photo Jānis B
      Jānis B

      I once tried to find out if there is an easy, generic way a method could determine own "parameter bindings", in order to implement generic method call "caching" mechanism (caching of method call results)... and didn't find any 🙂

      Author's profile photo Tolga POLAT
      Tolga POLAT

      Hi,

      Is there any plan for class constuructor with setter method. Like this

      data(oref) =

      new class_type( some_parameter )->set_other_parameter1( other_parameter1 )

                                                              ->set_other_parameter2( other_parameter2 ).

      I know this is not releated but I just wonder.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      I'm not sure if I understand your question (class constructor?), but the above syntax worked for NEW since it was introduced with ABAP 7.40, see NEW - Classes:

      Like an object reference variable of the type class, a constructor expression NEW class( ... ) can be specified before the object component selector -> and in chained attribute accesses and chained method calls.

      Author's profile photo Tolga POLAT
      Tolga POLAT

      Sorry for my bad English 🙂

      Let me explain my question like this:

      in JAVA  we can use setter method like this :

      class mycls{

      private int counter;

      private string text;

      public void mycls(int i){

           this.counter = i;

      }

      public void set_text(string text){

      /* this is optional attribute */

      this.text = text;

      }

      }

      now we can use this code like this:

      mycls my_cls = new mycls(5).set_text("This is setter");

      I try to explain this kind of usage of setter method.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Let me answer in ABAP:

      CLASS mycls DEFINITION.

         PUBLIC SECTION.

           METHODS:

             constructor IMPORTING i TYPE i,

             set_text IMPORTING text       TYPE string

                      RETURNING VALUE(ref) TYPE REF TO mycls.

         PRIVATE SECTION.

           DATA:

             counter TYPE i,

             text    TYPE string.

      ENDCLASS.

      CLASS mycls IMPLEMENTATION.

         METHOD constructor.

           counter = i.

         ENDMETHOD.

         METHOD set_text.

           me->text = text.

           ref = me.

         ENDMETHOD.

      ENDCLASS.


      Now we can use this code like this:


      DATA(my_cls) = NEW mycls( 5 )->set_text( `This is setter` ).


      The difference to your Java code is, that set_text must return the self reference me explicitly. Otherwise, you cannot chain in ABAP but have to write two statements.


      CLASS mycls DEFINITION.

         PUBLIC SECTION.

           METHODS:

             constructor IMPORTING i TYPE i,

             set_text IMPORTING text       TYPE string.

         PRIVATE SECTION.

           DATA:

             counter TYPE i,

             text    TYPE string.

      ENDCLASS.

      CLASS mycls IMPLEMENTATION.

         METHOD constructor.

           counter = i.

         ENDMETHOD.

         METHOD set_text.

           me->text = text.

         ENDMETHOD.

      ENDCLASS.

      ...

      DATA(my_cls) = NEW mycls( 5 ).

      my_cls->set_text( `This is setter` ).


      Author's profile photo Tolga POLAT
      Tolga POLAT

      Thanks for your reply. I didn't know if we return class itself, we can chain. But I prefer your second example in my code.

      Actually I'm not Java developer, But I couldn't explain myself without writing code 🙂

      Author's profile photo Stefan Riedel-Seifert
      Stefan Riedel-Seifert

      Cool feature! Ihave used it until now sometimes in my own coding. But it cannot help me by the following problem: assume having an internal table of references, i.e. as a result from the query manager (as part of the persistence framework)

      CALL METHOD agent->get_persistent_by_query
        EXPORTING i_query = iquery
        RECEIVING result  instances.

      In order to process the result, i have to loop and cast to the right persistence:

      LOOP AT instances INTO DATA(instance).
        persistence ?= instance.
        CALL METHOD persistence->get_...... RECEIVING result = ..... .value.
      ENDLOOP.

      because instances is of type OSREFTAB and persistence my own class.

      It might be of interest to be able directly loop and cast in one step.

       

       

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

       

      I see, you want something like

      DATA itab TYPE TABLE OF REF TO superclass WITH EMPTY KEY.
      
      DATA oref TYPE REF TO subclass.
      LOOP AT itab INTO oref CASTING.
      
      ENDLOOP.
      

      Can't you simply use the CAST operator in the loop instead?

      Author's profile photo Sandra Rossi
      Sandra Rossi

      Ouch, it was not clear in your post that CASTING was syntaxically incorrect, and I searched the most recent documentation because I didn't know this syntax. Maybe a little comment to say it explicitly ? like "<== invalid, CASTING not allowed here

      Author's profile photo Stefan Riedel-Seifert
      Stefan Riedel-Seifert

      ... that was my first try also, but doing so I will get a syntax error:

       LOOP AT instances INTO persistence casting. 
      
      Error: ".", "TO", "FROM", "WHERE", "WHERE ... .", or "USING KEY ..." is expected after "PERSISTENCE".
      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Sure, because we don't support it and I guess we won't, because you can use the CAST operator.

      Author's profile photo Stefan Riedel-Seifert
      Stefan Riedel-Seifert

      What a pity! To illustrate it, i have written thes lines of code:

      DATA:
        persistence TYPE REF TO cl_spfli_persistent,
        instances   TYPE osreftab.
      
      DATA(agent) = ca_spfli_persistent=>agent.
      
      TRY.
          CALL METHOD agent->if_os_ca_persistency~get_persistent_by_query
            EXPORTING
              i_query = cl_os_system=>get_query_manager( )->create_query( i_filter = |CARRID = PAR1| )
              i_par1  = 'LH'
            RECEIVING
              result  = instances.
      
          LOOP AT instances INTO DATA(instance)." casting persistence.
            persistence ?= instance.
      
          ENDLOOP.
      
        CATCH cx_os_object_not_existing.
      ENDTRY.

      Maybe, that the CAST-Statement is sufficient, but casting directly in the loop statement maybe a little bit smarter. The line doing the casting is quite obvious and can be supported by the abap language like the way of all the 'new' statements introduced in 7.40/7.50, which makes the coding much more smarter and readable. Nevertheless, thank you for giving this information.