一些 Next Generation ABAP Platform 的新语法用例

什么是 NGAP(Next Generation ABAP Platform)?

SAP NetWeaver 7.40 发布,并附带其 ABAP 应用服务器 AS ABAP 7.40。

在 AS ABAP 7.40 中,ABAP 语言具有一些不错的新特性。

AS ABAP 7.40 是 AS ABAP 7.31(又名 AS ABAP 7.03)的继承者,后者是基于 AS ABAP 7.0 构建的 AS ABAP 7.02 的继承者。

请注意,关于 ABAP 语言和 ABAP 语言环境 AS ABAP 7.31 及其 AS ABAP 7.40 不是 AS ABAP 7.30 的继承者。相反,AS ABAP 7.03 已重命名为 AS ABAP 7.31,因此 AS ABAP 7.40 是 AS ABAP 7.02 的后续版本。

AS ABAP 7.0 发布后,ABAP 语言的进一步开发主要在 7.10、7.20、7.30 代码行中完成,而大多数用户仍然使用 7.0x 代码行。为了让更大的开发者社区能够使用所有好的开发,几年前从 7.2 到 7.02 进行了一项主要功能的反向移植。 7.2 的所有功能(除了为 RFC 启用的基于类的异常和来自包违规的语法错误)在 7.02 中可用。

在 7.2 和 7.3 或 7.02 和 7.03(又名 7.31)之间没有增强 ABAP 语言。同时关闭 7.10、7.20、7.30 代码行。由于该代码行的大多数开发(尤其是那些与 ABAP 语言本身无关的增强功能)无论如何都向后移植到 7.03,因此 7.03 被重命名为 7.31,两个代码行合二为一:7.0x -> 7.31 行。
在这期间,为 SAP 内部使用打开了另一个 ABAP 代码行:基于 7.2 的 ABAP 8.0 到 8.04。这是有史以来第一个 ABAP 代码行,其中 ABAP 以非向下兼容的方式进一步开发。事实上,许多被认为已过时的功能已从该代码行中删除(甚至包括逻辑数据库)。新的 AS ABAP 是为 NGAP(下一代 ABAP 平台)制作的,并在内部用于 SAP 用于新产品(例如 Business by Design)的现代面向对象和基于框架的开发。当然,遗留 ABAP 程序很难在 NGAP 上运行。

随着 HANA 的出现,需要在 7.0x -> 7.31 系列中进一步开发 ABAP。第一个结果是 7.40。再次,发生了一个大的反向移植。这次从 8.0x 到 7.40。为 NGAP 开发的许多有用的 ABAP 功能回到了 7.0x 线——这一次是通过保持完全的向下兼容性(由于此限制,仍有一些功能尚未向后移植)。
从 7.40 开始,ABAP 在与内核版本捆绑的支持包中得到进一步开发。第一个可供客户使用的捆绑支持包是带有内核 7.40 的 SP02。紧随其后的是带有内核 741 的 SP05。更多捆绑的 SP 即将推出,每个都有自己的内核,因此具有新的 ABAP 功能。

COND

*&---------------------------------------------------------------------*
*& Report ZCAST2
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zcast2.

CLASS c1 DEFINITION.
ENDCLASS.

CLASS c2 DEFINITION INHERITING FROM c1.
ENDCLASS.

DATA: ref1 TYPE REF TO c1,
      ref2 TYPE REF TO c2.

ref1 = NEW c2( ).

IF ref1 IS INSTANCE OF c2.
  ref2 ?= ref1.
ENDIF.

TRY.
    ref2 ?= ref1.
  CATCH cx_sy_move_cast_error.
ENDTRY.

DATA: jerry1 TYPE REF TO c1,
      jerry2 TYPE REF TO c2.
DATA(lv) = COND boolean( WHEN jerry1 IS INSTANCE OF c2 THEN abap_true ELSE abap_false ).

WRITE: lv.
ASSERT lv = abap_false.

上面代码里,变量 lv 是一个 boolean 类型,其值通过 WHEN ... THEN ... ELSE ... 代码块计算出来。

另一个例子:

DATA: lv_string TYPE string,
      lv_count TYPE int4 value 1.

lv_string = 'Jerry' &&  COND #( WHEN lv_count = 1 THEN ' Hello' ELSE 'default'  ).

WRITE: / lv_string.

FILTERS

直接对一个内表根据某些条件进行过滤操作,返回过滤后的新内表:

*&---------------------------------------------------------------------*
*& Report ZFILTER
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZFILTER.

CLASS demo DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS main.
ENDCLASS.

CLASS demo IMPLEMENTATION.
  METHOD main.
    DATA carrid TYPE spfli-carrid VALUE 'LH'.
    cl_demo_input=>add_field( CHANGING field = carrid ).
    DATA cityfrom TYPE spfli-cityfrom VALUE 'Frankfurt'.
    cl_demo_input=>request( CHANGING field = cityfrom ).

    DATA spfli_tab TYPE STANDARD TABLE OF spfli
                   WITH EMPTY KEY
                   WITH NON-UNIQUE SORTED KEY carr_city
                        COMPONENTS carrid cityfrom.

    SELECT *
           FROM spfli
           INTO TABLE @spfli_tab.

    DATA(extract) =
      FILTER #( spfli_tab USING KEY carr_city
                  WHERE carrid   = CONV #( to_upper( carrid ) ) AND
                        cityfrom = CONV #( to_upper( cityfrom ) ) ).

    cl_demo_output=>display( extract ).

    DATA(rest) =
      FILTER #( spfli_tab EXCEPT USING KEY carr_city
                  WHERE carrid   = CONV #( to_upper( carrid ) ) AND
                        cityfrom = CONV #( to_upper( cityfrom ) ) ).

    ASSERT lines( extract ) + lines( rest ) = lines( spfli_tab ).

  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  demo=>main( ).

另一个例子:

*&---------------------------------------------------------------------*
*& Report ZFILTER_TEST
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZFILTER_TEST.

*Here, the internal table itab must have at least one sorted key or one hash key used for access.
*This can be either the primary table key used without specifying USING KEY or
* by specifying its name primary_key after USING KEY,
*or a secondary table key used by specifying its name after USING KEY.

TYPES: BEGIN OF ty_language,
         name TYPE string,
         year TYPE i,
       END OF ty_language.

TYPES: tt_language TYPE STANDARD TABLE OF ty_language with key PRIMARY_KEY COMPONENTS name with UNIQUE SORTED KEY
        aa COMPONENTS year.

"types: tt_language TYPE STANDARD TABLE OF ty_language.

TYPES: BEGIN OF ty_employee,
         empl_name TYPE string,
         lang_name TYPE string,
         year TYPE i,
       END OF ty_employee.

TYPES: tt_employee TYPE STANDARD TABLE OF ty_employee WITH KEY empl_name.

data:lt_language type tt_language.

lt_language = value #( ( name = 'ABAP' year = 10 )
                       (  name = 'Java' year = 7  ) ).

DATA: lt_employee1 TYPE tt_employee,
      lt_employee2 TYPE tt_language.

* way1
LOOP AT lt_language ASSIGNING FIELD-SYMBOL(<line>) WHERE year >= 10.
   DATA(ls_employee) = value ty_employee( empl_name = 'Jerry' lang_name = <line>-name
   year = <line>-year ).
   APPEND ls_employee TO lt_employee1.
ENDLOOP.

lt_employee2 = FILTER tt_language( lt_language using key aa where year >= 10  ).

BREAK-POINT.

利用 LET 关键字定义的临时变量

*&---------------------------------------------------------------------*
*& Report ZLET
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZLET.

data: lv_string type string value '1'.


 data(lt_table) = VALUE string_table(
    FOR i = 1 WHILE i <= 100 (
      COND string( LET r3 = i MOD 3
                       r5 = i MOD 5 IN
                   WHEN r3 = 0 AND r5 = 0 THEN |FIZZBUZZ|
                   WHEN r3 = 0            THEN |FIZZ|
                   WHEN r5 = 0            THEN |BUZZ|
                   ELSE i ) ) ).

 CLASS cx_cant_be DEFINITION INHERITING FROM cx_no_check.
ENDCLASS.

cl_demo_output=>display(
  COND #( LET t = '120000' IN
          WHEN sy-timlo < t THEN
            |{ sy-timlo TIME = ISO } AM|
          WHEN sy-timlo > t AND sy-timlo < '240000' THEN
            |{ CONV t( sy-timlo - 12 * 3600 ) TIME = ISO } PM|
          WHEN sy-timlo = t THEN
            |High Noon|
          ELSE
            THROW cx_cant_be( ) ) ).

 BREAK-POINT.

Table 表达式

*&---------------------------------------------------------------------*
*& Report ZTABLE_EXPRESSION
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZTABLE_EXPRESSION.

data: lt_table type string_table,
      lv_jerry type string value 'Jerry',
      lv_scala type string value 'Scala'.

lt_table = value #( ( lv_jerry ) ( lv_scala ) ).

* Jerry and the line of LT_TABLE are incompatible
" lt_table = value #( ( 'Jerry' ) ).
TYPES:
   BEGIN OF struc,
      col1 TYPE c LENGTH 2,
      col2 TYPE i,
      col3 TYPE i,
   END OF struc.

DATA itab TYPE SORTED TABLE OF struc WITH UNIQUE KEY col1
          WITH UNIQUE SORTED KEY sec_key COMPONENTS col2.

itab = VALUE #( ( col1 = 'AA' col2 = 5 col3 = 100 )
                ( col1 = 'BB' col2 = 4 col3 = 100 )
                ( col1 = 'CC' col2 = 3 col3 = 100 )
                ( col1 = 'DD' col2 = 2 col3 = 100 )
                ( col1 = 'EE' col2 = 1 col3 = 100 ) ).

DATA(wa) = itab[ 1 ].

ASSIGN itab[ col1 = 'BB' ] TO FIELD-SYMBOL(<fs>).

cl_demo_output=>display( itab[ 3 ] ).

IF line_exists( itab[ KEY sec_key col2 = 2 ] ).
ENDIF.

DATA(line) = itab[ KEY sec_key col2 = 4 ].

TRY.
DATA(not) = itab[ KEY sec_key col2 = 333 ].
CATCH cx_root.
ENDTRY.

itab[ col1 = 'EE' ]-col3 = 555.

推荐阅读更多精彩内容