Skip to Content
Author's profile photo Horst Keller

ABAP News for Release 7.40 – ABAP Objects

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.

Assigned Tags

      43 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Dirk Wittenberg
      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog 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( ).

       

      Author's profile photo Rüdiger Plantiko
      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog 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

      Author's profile photo Former Member
      Former Member

      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.

      Author's profile photo Naimesh Patel
      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog 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.

      Author's profile photo Alexandre Fernandez Gasques
      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

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

      Hi Alex,

       

      Aren't some ABAP operarators not overloaded already since they behave differently for different types? OR what do you wish?

       

      About Boolean, you are not alone http://scn.sap.com/people/horst.keller/blog/2013/06/22/abap-news-for-release-740--new-internal-table-functions#comment-366989

       

      Best

       

      Horst

      Author's profile photo Alexandre Fernandez Gasques
      Alexandre Fernandez Gasques

      I'm referring to this operator overloading

       

      Thanks for your reply.

      Author's profile photo Horst Keller
      Horst Keller
      Blog 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.

      Author's profile photo Volodymyr Shcheglov
      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? (;

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

      I think so, but I'm only a documentation writer ..

      Author's profile photo Former Member
      Former Member

      Well I think that the absence of booleans is not a big thing.

      Implementing method overloading in the language is a bigger (wanted) issue...

      Author's profile photo Former Member
      Former Member

      Hi,

      thanks for making this concept more easy....

      Author's profile photo Julian Phillips
      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...

      Author's profile photo Horst Keller
      Horst Keller
      Blog 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 ...

      Author's profile photo Julian Phillips
      Julian Phillips

      Excellent, I look forward to that.

      Author's profile photo Rüdiger Plantiko
      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog 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

      Author's profile photo Rüdiger Plantiko
      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog 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

      Author's profile photo Former Member
      Former Member

      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.

      Author's profile photo Rüdiger Plantiko
      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

      Author's profile photo Former Member
      Former Member

      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.

      Author's profile photo Rüdiger Plantiko
      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.

       

      )

      Author's profile photo Horst Keller
      Horst Keller
      Blog 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

      Author's profile photo Rüdiger Plantiko
      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 ...'

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

      SWITCH is a constructor operator for constructor expressions.  The general syntax is:

       

      ... operator type( ... ).

       

      The type can always be specified with # if it can be inferred at the current position.

       

      B.T.W. ABAP News for Release 7.40 - Constructor Operators COND and SWITCH

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

      I spy with my little eye ...

      /wp-content/uploads/2014/03/predicate_method_417720.jpg

       

      (Sneak Preview 7.40, SP08)

      Author's profile photo Rüdiger Plantiko
      Rüdiger Plantiko

      Wow, that's great news!

       

      Will this work like a tacit "IS NOT INITIAL", or does it only work for expression results of data type ABAP_BOOL ?

      Author's profile photo Horst Keller
      Horst Keller
      Blog 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.

      Author's profile photo Former Member
      Former Member

      Hi,

       

      Thanks for your post. It is really helpful.

      Author's profile photo Former Member
      Former Member

      Hi,

      Quite helpful post

       

      !Thanks

      Author's profile photo Uwe Fetzer
      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)

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

      Inline declarations can be used at write-only positions and - of course not - at read-only positions.

      Author's profile photo Uwe Fetzer
      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) ).

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

      Oooopsi, ....

       

      I´ll check it out tomorrow.

      Author's profile photo Horst Keller
      Horst Keller
      Blog 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 ,

       

       

       

       

       

       

       

       

       

       

       

       

       

       

      Author's profile photo Uwe Fetzer
      Uwe Fetzer

      Thank you! Never would have guessed.

       

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

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

      right to exist ....

      Author's profile photo Pawel Jagus
      Pawel Jagus

      Hello Horst,

      how come this syntax compiles?

          CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
            EXPORTING
              buffer = lcl_main=>convert_to_xstring(
                         EXPORTING
                           i_param1 = 1
                           i_param2 = 2
                       )
            TABLES
              binary_tab = lt_binary_tab.

      and this not?

          CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
            EXPORTING
              buffer = lcl_main=>convert_to_xstring(
                           i_param1 = 1
                           i_param2 = 2
                       )
            TABLES
              binary_tab = lt_binary_tab.

      The whole programm is here.

      REPORT ZZY.
      
      CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
        PUBLIC SECTION.
          CLASS-METHODS:
            convert_to_xstring
              IMPORTING
                i_param1 TYPE i
                i_param2 TYPE i
              RETURNING
                VALUE(rv_result) TYPE xstring,
            main.
      ENDCLASS.
      
      CLASS lcl_main IMPLEMENTATION.
        METHOD convert_to_xstring.
        ENDMETHOD.
      
        METHOD main.
          DATA: lt_binary_tab TYPE STANDARD TABLE OF x.
      
          DATA(lv_result) = convert_to_xstring( i_param1 = 1 i_param2 = 2 ).
      
          CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
            EXPORTING
              buffer = lcl_main=>convert_to_xstring(
                           i_param1 = 1
                           i_param2 = 2
                       )
            TABLES
              binary_tab = lt_binary_tab.
      
        ENDMETHOD.
      ENDCLASS.
      
      START-OF-SELECTION.
        lcl_main=>main( ).

      Without EXPORTING the error message is

      Error%20message

      Error message

      which is obviously not true, because I can put there a method call but with EXPORTING.

      Author's profile photo Oscar Alejandro Aranquiz Cortes
      Oscar Alejandro Aranquiz Cortes

      Hi.

      I also have the following issue with ABAP syntax.

      The following code can be activated:

          IF _posting_allowedi_par COND #WHEN THEN abap_true.

      ENDIF.

      But if I remove "= abap_true", we get the message "Error in logical expression".

          IF _posting_allowedi_par COND #WHEN THEN ).

      ENDIF.

      Any ideas?