Skip to Content

For ABAP Objects itself – meaning the statements for dealing with classes and objects in ABAP – there are two small but nice improvements in Release 7.40.

Parameter Interface of Functional Methods

Before Release 7.40 a functional method could have only importing parameters besides its returning parameter.

A functional method can now have exporting and changing parameters besides its returning parameter.

In functional method calls you can use the additions EXPORTING, IMPORTING, and CHANGING to pass parameters.

Example

The following kind of functional method declaration and invocation was not possible before Release 7.40.

CLASS class DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS do_something IMPORTING p1 TYPE i
                                         p2 TYPE i
                               EXPORTING p3 TYPE i
                                         p4 TYPE i
                               RETURNING VALUE(r) TYPE i.
ENDCLASS.

IF  class=>do_something( EXPORTING p1 = 333
                                   p2 = 444
                         IMPORTING p3 = a1
                                   p4 = a2 ) = 0.
  “work with a1, a2
ENDIF.

Interfaces in Test Classes

You know that you have to implement all the methods of each interface that you include in your classes with the INTERFACES statement.While this is OK for normal classes, since the user expects the interfaces to be implemented, it can be become rather tedious in test classes of ABAP Unit. Especially when creating test doubles by implementing interfaces in test classes it is cumbersome to implement (sometimes many, many ) empty interface methods that are not needed for testing. And since empty method implementations are reported by the extended program check, you even have to add a pragma ##needed to each of those!

Fortunately, there is now a new addition PARTIALLY IMPLEMENTED to the statement INTERFACES that can be used in test classes and makes an end to these problems (don’t tell me that you don’t have such problems since you are not testing …).

Example

The following example is an excerpt from an test include of a http-handler class. Since a http-handler normally works with objects like request or response of the ICF-framework, for standalone testing you have to create appropriate test doubles (mock framework) by implementing the according interfaces. In the case shown here, a class for a mock request is created by implementing if_http_request. Before Release 7.40 this was rather awkward, since you had to implement all of the about 50 interface methods! In Release 7.40 you have to implement only those that are needed for testing.

Before Release 7.40

CLASS mock_request DEFINITION FOR TESTING FINAL.
  PUBLIC SECTION.
    INTERFACES if_http_request.
ENDCLASS.

CLASS mock_request IMPLEMENTATION.
  METHOD if_http_request~get_form_field.
    value = SWITCH spfli-carrid( name WHEN ‘carrid’ THEN ‘LH’
                                      ELSE space ).
  ENDMETHOD.

  METHOD if_http_entity~set_cdata.     ENDMETHOD.     “##needed

  METHOD if_http_entity~set_data.      ENDMETHOD.     “##needed

  METHOD if_http_entity~add_multipart. ENDMETHOD.     “##needed

  METHOD if_http_entity~append_cdate.  ENDMETHOD.     “##needed

  …

ENDCLASS.

Release 7.40

CLASS mock_request DEFINITION FOR TESTING FINAL.
  PUBLIC SECTION.
    INTERFACES if_http_request PARTIALLY IMPLEMENTED.
ENDCLASS.

CLASS mock_request IMPLEMENTATION.
  METHOD if_http_request~get_form_field.
    value = SWITCH spfli-carrid( name WHEN ‘carrid’ THEN ‘LH’
                                      ELSE space ).
  ENDMETHOD.
ENDCLASS.

To report this post you need to login first.

41 Comments

You must be Logged on to comment or reply to a post.

  1. Dirk Wittenberg

    Hi,

     

    thank’s for posting this blog.

     

    So far I looked forward to the new features of ABAP syntax in 7.40 but allowing exporting and changing parameters in functional methods shocks me a bit! What shall it be good for? Allowing this mix of returning- exporting- and changing-parameters in my optionion just leads to overloading methods with more than one responsibility and causing side-effects.

     

    On the other side the feature “PARTIALLY IMPLEMENTED” let’s me shout “Well done SAP!”.

     

    Regards,

    Dirk

    (0) 
    1. Horst Keller Post author

      Hi Dirk,

       

      Allowing exporting and changing parameters in functional methods does not mean that you should now go and create extensive parameter interfaces. The programming guideline for slim method interfaces is of course still valid and the ideal method has still some few importing and one returning parameter.

       

      Nevertheless, the technical restriction that a functional method should only have importing parameters besides its returning parameter was a bit severe and needlessly inhibited some very nice patterns. One I have shown above (I used that in my programs, the moment the feature appeared; use case: fetching and checking some internal tables with one returning parameter that tells me, if fetching and checking was succesful).

       

      Another one is method chaining. If you have a class where each instance method returns the self reference me, you can write code without the need of explicit reference variables.

       

      Before 7.40:

       

      DATA in TYPE REF TO if_demo_input.
      in = cl_demo_input=>new( ).

      in->add_field( CHANGING field = dobj_1 ).
      in->add_field( CHANGING field = dobj_2 ).

      in->request( ).

       

      With 7.40:

       

      cl_demo_input=>new(
      )->add_field( CHANGING field = dobj_1
      )->add_field( CHANGING field = dobj_2

      )->request( ).

       

      (0) 
      1. Rüdiger Plantiko

        Horst,

         

        I like method chaining, but not yet in ABAP. For the simple reason that it is still not possible to add the linebreaks at a reasonable place, like so:

         

         

        cl_demo_input=>new( )

          ->add_field( CHANGING field = dobj_1 )

          ->add_field( CHANGING field = dobj_2 )

          ->request( ).

         

         

        This would give a syntax error, as well as  this:

         


        cl_demo_input=>new( )->

          add_field( CHANGING field = dobj_1 )->

          add_field( CHANGING field = dobj_2 )->

          request( ).


        The only version in which method chaining is possible is the one you proposed above, filling the line-break in the parameter list:


        cl_demo_input=>new(

          )->add_field( CHANGING field = dobj_1

          )->add_field( CHANGING field = dobj_2

        )->request( ).


        This looks a bit “broken” to me. Are there plans to allow the other notation?


        Regards,

        Rüdiger

        (0) 
        1. Horst Keller Post author

          Hi Rüdiger,

           

          In ABAP there are strict  rules, where you must use at least one whitespace (blank character or linebreak) and where you can’t. You must use one or more whitespace between tokens (there are enough complaints about this too) but you cannot use a whitesapce within a token and especially not behind or in front of a selector. It is not possible to write “struct – comp”, “class => comp”, “oref -> comp”. That’s how it is and currently there are no plans to change that.

           

          One reason is, of course, backward compatibility:

           

          DATA result TYPE string.
          DATA struct TYPE string.
          DATA comp  TYPE STRING.
          CONCATENATE struct  comp INTO result.

           

          Changing the fundamental whitespace rules of ABAP is such a fundamental thing that it cannot be done without a versioning of the language (dream). E.g. a new version where all lists must be comma separated to circumvent ambiguities as above.

           

          Regards,

           

          Horst

          (0) 
    2. Robin Fillerup

      I totally agree with Dirk. Working with only methods that have a returning paramter will automatically reduce the size of your methods. Chances are there that if the method can only return 1 thing, it only performs 1 task.

      Best regards, Robin.

      (0) 
  2. Naimesh Patel

    Hello Horst,

     

    Thanks for the “glimpse” of the ABAP 740.

     

    When using the RETURNING, EXPORTING, It would fun to decide which variables would be returned as RETURNING vs which would be sent back as EXPORTING.

     

    Regarding the PARTIALLY IMPLEMENTED, you have mentioned:

    Fortunately, there is now a new addition PARTIALLY IMPLEMENTED to the statement INTERFACES that can be used in test classes and makes an end to these problems

     

    Can it be used out side the Test class – class without addition FOR TESTING?

     

    Thanks,
    Naimesh Patel

    (0) 
    1. Horst Keller Post author

      Why, with RETURNING you define the returning parameter and with EXPORTING you define exporting parameters. You assign the variables to the parameters in the method as you wish.

       

      No, PARTIALLY IMPLEMENTED can be used in test classes only.

      (0) 
  3. Alexandre Fernandez Gasques

    Hi Horst,

     

    I’m really excited about the progress of our language. Recently I was able to start using the features of version 7.02 in my clients and I have reduced lines and intermediate variables drastically. I look forward to using the 7.4 features soon.

     

    I have two questions for you:

    1. What about operator overloading? Any plans for this?

    2. What about basic type boolean? Currently, there is no single mode or standard way to follow. Sometimes i found char types with a flag, others constants with 0/1, others tristate boolean (‘-‘ = False, ‘X’ = True, space = Undefined)… I think it’s quite necessary to ensure homogeneity of code and it can reduce a bit the database costs and space in disk.

     

    Best regards,

    Alex

    (0) 
        1. Horst Keller Post author

          Sure, I looked this up. The “overloading” we have up to now is only for built-in types (e.g. VALUE behaves differently for elementary, structured or table types). But there is no overloading planned for self defined types.

          (0) 
      1. Volodymyr Shcheglov

        Horst Keller wrote:

         

                               

         

        About Boolean, you are not alone…

        Best

         

        Horst

         

                           

        Currently, with logical functions it’s possible to omit comparison in IFs:

         

        IF matches( val = lv_text regex = ‘[[:alpha:]]+’ ).

        ENDIF.

         

        However, if a method is declared as returning an ABAP_BOOL parameter, it’s impossible to write the code the same way:

         

        IF lo_myobj->method( ).

        ENDIF.

         

        It would be great to unify boolean functions/methods behaviour. Don’t you think so? (;

        (0) 
  4. Julian Phillips

    Hi Horst,

     

       good blog, thanks, always interesting to read up on the new features of ABAP just around the corner. Do you have any plans for an updated version of your ABAP Objects book to include all of these? If so I’ll be placing an order…

    (0) 
    1. Horst Keller Post author

      In fact yes. We’re currently writing an ABAP Language Book as successor of ABAP Objects (less tools, less UI, more language) that describes modern expression enabled ABAP and includes the 7.40 stuff. We passed the deadline several times already but I hope to find some time in autumn …

      (0) 
  5. Rüdiger Plantiko

    I didn’t find the following feature in any dream list or wish list by Horst or anybody else:

     

    Custom Predicate Methods

     

    Like system predicate functions, the developer can define methods as predicate methods, by flagging the (new 🙂 ) checkbox “Predicate Method” in the method’s attributes view. 

     

    Only requirement for setting this flag is that the method has a return parameter of elementary data type CHAR1 (of course, something like FLAG or XSDBOOLEAN will be the concrete data element in all cases).

     

    Predicate methods can be used like system functions in boolean expressions, but it is not necessary to compare their result value with ‘X’ or space (or ABAP_TRUE or ABAP_FALSE):

     

    Example: If the methods is_variant and allows_variants in the following example are predicate methods, we could write:

     

    if lo_article->is_variant( ) and lo_order->allows_variants( ).

    lo_order->insert_variant( lo_article ).

    endif.

     

    Regards,

    Rüdiger

    (0) 
    1. Horst Keller Post author

      On a first glance, I have two observations to add:

       

      • Classes are strictly source code based, It wouldn’t be a “flag in the method’s attribute view”, but it would be a new addition to the METHODS statement.
      • This addition would help for methods only. What about other functions and expressions?

       

      But I’m informed that our developers are already thinking about a general solution and maybe there will be a general short form

       

      IF expr.
        …
      ENDIF.

       

      in an upcoming SP.

       

      Best

       

      Horst

      (0) 
      1. Rüdiger Plantiko

        maybe there will be a general short form

         

        IF expr.
          …
        ENDIF.

         

        in an upcoming SP.

         

        This was more than I dared to expect! Looking forward to the SP! (But, yes, I got the “maybe” too).

         

        As fas as I can guess, this might be the forthcoming functionality: The parser detects that the IF condition is not a complete logical expression but a general expression, and auto-completes the generated bytecode to form a logical expression: It will compare the result with ‘X’ (or additionally use  ‘<> 0’ for numerical results?)

         

        Regards,

        Rüdiger

        (0) 
        1. Horst Keller Post author

          Yep, an idea to cut the Gordian knot could be simply a short form:

           

          ... expr [IS NOT INITIAL] ...

           

          But what also must be considered: the short form alredy exists!

           

          … [expr IN] seltab …

           

          -> The parser must exclude expresssions that are selection tables.

           

          Maybe, maybe …

           

          Best

           

          Horst

          (0) 
        2. Manish Kumar

          For multiple expressions with OR, i like to write this way.

          CASE abap_true.
            WHEN lo_article->is_variant( ) OR lo_order->allows_variants( ).
               lo_order->insert_variant( lo_article ).
          ENDCASE.

          (0) 
          1. Rüdiger Plantiko

            Hi Manish,

             

            I have seen this idiom elsewhere, but – to state it frankly – I don’t like it. It’s not natural to put the constant ABAP_TRUE at a place in the code where a decision variable is expected.

             

            In my opinion, the ABAP_TRUE belongs to the right-hand side: The relevant thing is the expression itself. It deserves the higher attention that is spent to the first part of a statement.

             

            Regards,
            Rüdiger

            (0) 
            1. Manish Kumar

              I had seen it in radio button handling code. ‘X’ next to Case, and a number of radiobutton names next to When. At a time only of them would be true.

              (0) 
              1. Rüdiger Plantiko

                Yes, admittedly, this is a use case which seems an exception from the rule. Any idea to improve this code is welcome:

                 

                case ABAP_TRUE.

                when P_RB_USD.

                   …

                when P_RB_CHF.

                   …

                when P_RB_EUR.

                   …

                endcase.

                 

                (which is obviously better readable than

                 

                if P_RB_USD EQ ABAP_TRUE.

                elseif P_RB_CHF EQ ABAP_TRUE.

                elseif P_RB_EUR EQ ABAP_TRUE.

                endif.

                 

                )

                (0) 
          2. Horst Keller Post author

            Well yes, we know that patterns like the following are widely used:

             

            CASE constant.

              WHEN expression1.

                …

              WHEN expression2.

                …

            ENDCASE.

             

            But this is not good style and it should be the other way around;

             

            CASE expression.

              WHEN constant1.

                …

              WHEN constant2.

                …

            ENDCASE.

             

            The new SWITCH operator does not support the first but only second pattern!

             

             

            OK, for radio buttons or similar scenarios you can write already nowadays :

             

            CASE ‘X’

              WHEN radio1.

                …

              WHEN radio2 OR radio3.

              …

            ENDCASE.

             

            This will not vanish, so why discuss it here?

             

            Note that the above CASE is already a kind of short form, since each WHEN stands for something like

             

            IF ‘X’ = radio2 OR ‘X’ = radio3.

             

            -> No need/possibility to write CASE/WHEN shorter.

             

             

            Best

             

            Horst

            (0) 
            1. Rüdiger Plantiko

              Thanks for pointing to the new SWITCH syntax.

               

              AFAIS, it doesn’t help with the above radiobutton example, though.

               

              Also, in the example from the docu

               

              … = SWITCH string( sy-index

                                     WHEN 1 THEN ‘one’

                                     WHEN 2 THEN ‘two’

                                     WHEN 3 THEN ‘three’

                                     ELSE THROW cx_overflow( ) ).

               

              I don’t like the type “string” at the prominent place.

               

              I would be a friend of SWITCH, if the type was optional, like this:

               

              … = SWITCH( sy-index

                                     WHEN 1 THEN ‘one’

                                     WHEN 2 THEN ‘two’

                                     WHEN 3 THEN ‘three’

                                     ELSE THROW cx_overflow( ) ).


              since naturally, at the place directly following the SWITCH keyword, we are expecting the decision variable or decision expression, which is the most important part of the switch/case expression.


              The type could be inferred automatically, or there could be a default type (STRING, say).


              P.S. (edited): Just saw in the docu that the automatic type inference could be used with ‘SWITCH # ( sy-index …’

              (0) 
        1. Horst Keller Post author

          Will this work like a tacit “IS NOT INITIAL”?

           

          ‘xactly. The return value can have any type.

           

          It will not be any expression but functional method calls only.

          (0) 
  6. Uwe Fetzer

    In my current fun project Neo4a: The Neo4j ABAP Connector I came across a strange behaviour and I don’t know why:

     

    Assume we have a method declared as

        CLASS-METHODS: main

          EXPORTING e_parm        TYPE string

          RETURNING VALUE(r_parm) TYPE string.

    The following statement is syntactically correct:

    DATA two TYPE string.

    DATA(one) = lcl_app=>main( IMPORTING e_parm = two ).

     

    But if I want to use inline declaration on the importing parameter, I’m getting a syntax error:

    inline.PNG

     

    Is it intended so or a kernel problem?

    (NW 7.40 SP8, Kernel 742 SP19)

    (0) 
      1. Uwe Fetzer

        Maybe just a misunderstanding: this is – of course – “importing” from the callers view .

         

        The same without requesting the RETURNING parameter works:

        PUBLIC SECTION.

          CLASS-METHODS: main

            EXPORTING e_parm TYPE string

            RETURNING VALUE(r_parm) TYPE string

         

        lcl_app=>main( IMPORTING e_parm = data(two) ).

        (0) 
        1. Horst Keller Post author

          The reason for that is somewhat hidden in Declaration Positions.

           

          Actual parameters for output parameters and return values of methods for standalone method calls

           

           

          -> Not for method calls as RHS or in expressions. syntax error in:

           

          DATA(d1) =  demo=>main( IMPORTING exp = DATA(d2) ).

           

          In the following case, you also get a syntax error.

           

            IF 1 = demo=>main( IMPORTING exp = DATA(d1) ).

            ENDIF.

           

           

          The compiler interpretes operand positions in expressions always as read-only positions.

           

          The workaround for your case is:

           

          demo=>main(

            IMPORTING exp = DATA(d2)
            RECEIVING ret = DATA(d1) ).

           

          So, my original answer wasn’t too wrong but admittedly too shortsighted ,

           

           

           

           

           

           

           

           

           

           

           

           

           

           

          (0) 
          1. Uwe Fetzer

            Thank you! Never would have guessed.

             

            Finally a “Daseinsberechtigung” (sorry, no English word available: the right to exist) for the keyword RECEIVING

            (0) 

Leave a Reply