ABAP 面向对象与其他语言的区别

举报
雨绸缪 发表于 2023/05/29 16:52:24 2023/05/29
【摘要】 引言还记得在学习 ABAP 开发时,学到面向对象 ALV 的时候,就没耐心继续往下学习了,直到在开发过程中踩过无数坑之后,才想起 OOP(面向对象编程) 的威力。OO ABAP 和 JAVA 是面向对象的编程风格。 ABAP/4 被扩展以支持 OO(面向对象) 概念。 Java、C++ 等面向对象的概念在 OO ABAP 中被采用,但 ABAP 也会有一些特有的特性,这意味着 ABAP 中...

image.png

引言

还记得在学习 ABAP 开发时,学到面向对象 ALV 的时候,就没耐心继续往下学习了,直到在开发过程中踩过无数坑之后,才想起 OOP(面向对象编程) 的威力。

OO ABAP 和 JAVA 是面向对象的编程风格。 ABAP/4 被扩展以支持 OO(面向对象) 概念。 Java、C++ 等面向对象的概念在 OO ABAP 中被采用,但 ABAP 也会有一些特有的特性,这意味着 ABAP 中有一些 JAVA 不支持的功能,反之亦然。需要考虑的另一个重要方面是 ABAP 语言用于商业软件开发。存在两种情况,ABAP 实现面向对象的方式不同于您从其他面向对象编程语言(如 C++、Java 或 C#)中了解到的方式。 你可以称这些为“限制”,但实际上,这些情况并没有真正降低语言的能力,只是让语法更冗长了一点。

相似之处:OO ABAP 和 JAVA 等其他面向对象语言一样,满足三大特点:继承、多态、封装。

那么不同之处呢?

OO ABAP 没有重载功能

重载意味着一个类提供多个名称完全相同但参数略有不同的方法。

例如,您可以有一个接收字符串输入参数的方法日志变体,以及另一个接收整数的方法变体。 编译器分析调用方法的方式,并引导调用正确的方法。

虽然重载是 Java 中的常见模式,但 ABAP 不支持它并强制每个方法名称在类中只出现一次。 这种限制纯粹是语法上的,不会降低语言的表达能力。 例如,ABAP 会强制您将 LOG_STRING 方法与 LOG_INTEGER 方法区分开来,从而降低代码的可读性,但我们仍然能够记录字符串和整数。

人们有时会争辩说 OPTIONAL 输入参数可以弥补过载的不足。 然而,这种说法只是部分正确。 重载使您能够表达哪些参数组合构成有效输入。 可选参数还允许组合没有意义的输入参数。 例如,一个带有两个可选输入参数 STRING 和 INTEGER 的 LOG 方法可以同时使用这两个参数调用,或者根本不调用 - 这两种情况方法的开发人员可能甚至没有考虑过并且没有进行单元测试,因此会导致意想不到的结果。

构造函数概念不同

构造函数概念在 OO ABAP 中的处理方式非常不同。

CLASS zcl_vendor DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
    DATA gv_lifnr TYPE lifnr READ-ONLY.

    METHODS constructor
      IMPORTING
        !iv_lifnr TYPE lifnr.

    METHODS get_banlance
      RETURNING 
        VALUE(rv_balance) TYPE dmbtr.
  PROTECTED SECTION.
  PRIVATE SECTION.
    DATA:
      gv_balance      TYPE dmbtr,
      gv_balance_read TYPE abap_bool.
ENDCLASS.



CLASS zcl_vendor IMPLEMENTATION.

  METHOD constructor.
    " check if iv_lifnr exists in lfa1 and raise error if not
    gv_lifnr = iv_lifnr.
  ENDMETHOD.

  METHOD get_banlance.
    IF gv_balance_read EQ abap_false.
      " read vendor balance from bsik, bsak, etc into gv_balance
      gv_balance_read = abap_true.
    ENDIF.
    rv_balance = gv_balance.
  ENDMETHOD.
ENDCLASS.

OO ABAP 中的类/接口有着独特的事件

OO ABAP 中的类/接口以及属性和函数都有事件。事件概念是 OO ABAP的一个重要特征,其中一个对象引发事件;根据开发要求,数据变更、数据修改、搜索帮助时用到。

image.png

类定义如下

CLASS lcl_event_receiver DEFINITION.
  PUBLIC SECTION.
    METHODS data_changed FOR EVENT data_changed OF cl_gui_alv_grid
      IMPORTING er_data_changed
                  e_onf4
                  e_onf4_before
                  e_onf4_after
                  e_ucomm.
    METHODS handle_modify
                  FOR EVENT data_changed_finished OF cl_gui_alv_grid
      IMPORTING e_modified et_good_cells.


    METHODS handle_f4 FOR EVENT onf4 OF cl_gui_alv_grid
      IMPORTING e_fieldname
                  es_row_no
                  er_event_data
                  et_bad_cells
                  e_display.


ENDCLASS.                    "LCL_EVENT_RECEIVER DEFINITION

方法实现如下:

CLASS lcl_event_receiver IMPLEMENTATION.
  METHOD data_changed.
    PERFORM handle_data_changed USING er_data_changed.
  ENDMETHOD.
  METHOD handle_modify.
    PERFORM handle_data_finish USING e_modified et_good_cells.
  ENDMETHOD.                    "HANDLE_MODIFY



  METHOD handle_f4.
    FIELD-SYMBOLS: <fs_alv> LIKE gs_out.
    CASE e_fieldname.
      " 写自己的逻辑
    ENDCASE.

* 设置后,alv稳定刷新
    PERFORM refresh_table_alv.
  ENDMETHOD.

ENDCLASS.                    "LCL_EVENT_RECEIVER IMPLEMENTATION

FORM refresh_table_alv .  
  gs_stbl-row = 'X'." 基于行的稳定刷新  
  gs_stbl-col = 'X'." 基于列稳定刷新  
  CALL METHOD gcl_alv_grid->refresh_table_display  
    EXPORTING  
      is_stable = gs_stbl.  
  
ENDFORM. " REFRESH_TABLE_ALV

具体函数 HANDLE_DATA_CHANGED

*&---------------------------------------------------------------------*
*&      Form  HANDLE_DATA_CHANGED
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_ER_DATA_CHANGED  text
*----------------------------------------------------------------------*
FORM handle_data_changed  USING    p_er_data_changed
                          TYPE REF TO cl_alv_changed_data_protocol.

  DATA: mod_data        TYPE lvc_t_modi,
        gs_out_mod_data TYPE lvc_s_modi.

  mod_data = p_er_data_changed->mt_mod_cells.
  LOOP AT mod_data INTO gs_out_mod_data.

  ENDLOOP.

ENDFORM.

具体函数 handle_data_finish,如下:

*&---------------------------------------------------------------------*
*&      Form  HANDLE_DATA_FINISH
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_E_MODIFIED  text
*      -->P_ET_GOOD_CELLS  text
*----------------------------------------------------------------------*
FORM handle_data_finish  USING    e_modified TYPE char01
                                  et_good_cells TYPE lvc_t_modi.

  DATA: eh_good_cells TYPE lvc_s_modi.

  IF e_modified = 'X'.
    LOOP AT et_good_cells INTO eh_good_cells.      " 修改的行
      UNASSIGN: <f_out>.
      READ TABLE gt_out ASSIGNING <f_out> INDEX eh_good_cells-row_id.
      IF sy-subrc = 0.

        CLEAR: gs_out.
        LOOP AT gt_out INTO gs_out WHERE asnum = <f_out>-asnum.
          " 显示当前登录id
          CALL METHOD cl_gui_frontend_services=>get_user_name
            CHANGING
              user_name            = c_str
            EXCEPTIONS
              cntl_error           = 1
              error_no_gui         = 2
              not_supported_by_gui = 3
              OTHERS               = 4.

          CALL METHOD cl_gui_cfw=>flush
            EXCEPTIONS
              cntl_system_error = 1
              cntl_error        = 2.

          CALL 'ThUsrInfo' ID 'OPCODE' FIELD opcode_usr_attr
          ID'TERMINAL' FIELD terminal.

          gs_out-erdat = sy-datum.
          gs_out-erzet = sy-uzeit.
          gs_out-ernam = c_str.
          gs_out-zlogin = terminal.
          CASE eh_good_cells-fieldname.
            WHEN ''.  " 写实际逻辑

            WHEN OTHERS.
          ENDCASE.
        ENDLOOP.
      ENDIF.
    ENDLOOP.

    " 稳定刷新
    PERFORM refresh_table_alv.
  ENDIF.
ENDFORM.

OO ABAP 没有容器或者集合

ABAP 没有 C++ 中 STL 的容器,也没有 Java 中强大的集合。

据我所知,最大的区别——集合(ArrayListVectorLinkedListQueueHashtableTreeMapLinkedHashMapLinkedHashSetTreeSet)在 Java 中扮演着重要的角色;

OO ABAP 中没有同样的功能。如果我们需要集合的时候,例如处理一堆数据,就可以使用内部表(internal table, 简称 it)和工作区( work area,简称 wa)。

接口名称成为方法名称的一部分

当一个类实现一个接口时,该类通常会完全“接管”接口的方法,代码看起来就像这些方法是该类的原始片段一样。

例如,在 Java 中,如果类 Person 实现了指定一个名为 getEmail 的方法的 BusinessPartner 接口,您可以这样写:

Person alex = new Person();
alex.getEmail();

在 ABAP 中,从接口接管的方法会添加接口名称作为前缀。 对于前面的示例,ABAPer 需要编写:

DATA(bob) = NEW person( );
bob->business_partner~get_email( ).

如果一个类一次实现多个接口,此模式可避免名称冲突。

但是,请注意,如果变量的类型清楚地表明了预期的方法,则不需要接口的名称,如:

DATA charis TYPE REF TO business_partner.
charis = NEW person( ).
charis->get_email( ).

同样,这个事实并不是限制,因为您仍然可以让一个类完美地实现多个接口。 ABAP 的方法调用可能看起来只比其他编程语言长一点。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。