ABAPオブジェクトは、1999年にABAPへ導入されたオブジェクト指向の機能です。現在のABAP開発では、これが標準的な書き方となっています。
クラスの定義
ABAPのクラスは、定義部(DEFINITION)と実装部(IMPLEMENTATION)に分かれています。
CLASS lcl_order DEFINITION.
PUBLIC SECTION.
METHODS constructor
IMPORTING iv_order_id TYPE vbeln.
METHODS get_total
RETURNING VALUE(rv_total) TYPE p LENGTH 8 DECIMALS 2.
CLASS-METHODS create_from_db
IMPORTING iv_order_id TYPE vbeln
RETURNING VALUE(ro_order) TYPE REF TO lcl_order.
PROTECTED SECTION.
METHODS calculate_tax
RETURNING VALUE(rv_tax) TYPE p LENGTH 8 DECIMALS 2.
PRIVATE SECTION.
DATA mv_order_id TYPE vbeln.
DATA mt_items TYPE ty_items.
ENDCLASS.
CLASS lcl_order IMPLEMENTATION.
METHOD constructor.
mv_order_id = iv_order_id.
ENDMETHOD.
METHOD get_total.
LOOP AT mt_items INTO DATA(ls_item).
rv_total = rv_total + ls_item-amount.
ENDLOOP.
ENDMETHOD.
ENDCLASS.| セクション | アクセス範囲 |
|---|---|
| PUBLIC | どこからでもアクセス可能 |
| PROTECTED | 自クラスと継承したクラスからアクセス可能 |
| PRIVATE | 自クラス内からのみアクセス可能 |
インスタンスと静的
ABAPでは、インスタンスに属するものと、クラス自体に属するもの(静的)を、キーワードで区別します。
| 種類 | キーワード | アクセス演算子 |
|---|---|---|
| インスタンス属性 | DATA | obj->attr |
| 静的属性 | CLASS-DATA | class=>attr |
| インスタンスメソッド | METHODS | obj->method( ) |
| 静的メソッド | CLASS-METHODS | class=>method( ) |
" 従来の書き方
DATA lo_order TYPE REF TO lcl_order.
CREATE OBJECT lo_order
EXPORTING iv_order_id = '0000012345'.
" 現代的な書き方(7.4以降)
DATA(lo_order) = NEW lcl_order( iv_order_id = '0000012345' ).
" メソッド呼び出し
DATA(lv_total) = lo_order->get_total( ).
" 静的メソッド呼び出し(インスタンス不要)
DATA(lo_new) = lcl_order=>create_from_db( '0000012345' ).継承
CLASS lcl_rush_order DEFINITION
INHERITING FROM lcl_order.
PUBLIC SECTION.
METHODS get_total REDEFINITION.
ENDCLASS.
CLASS lcl_rush_order IMPLEMENTATION.
METHOD get_total.
" 親クラスの処理を呼ぶ
rv_total = super->get_total( ).
" 特急料金を加算
rv_total = rv_total * '1.2'.
ENDMETHOD.
ENDCLASS.ABAPは単一継承のみをサポートします。複数の親を持つことはできません。複数の振る舞いを組み合わせたい場合は、インタフェースを使います。
インタフェース
INTERFACE lif_printable.
METHODS print.
ENDINTERFACE.
CLASS lcl_invoice DEFINITION.
PUBLIC SECTION.
INTERFACES lif_printable.
ENDCLASS.
CLASS lcl_invoice IMPLEMENTATION.
METHOD lif_printable~print.
WRITE: / '請求書を印刷します'.
ENDMETHOD.
ENDCLASS.
" インタフェース参照で扱う
DATA lo_printable TYPE REF TO lif_printable.
lo_printable = NEW lcl_invoice( ).
lo_printable->print( ).インタフェースを使うと、実装クラスが何であれ同じように扱えます。「印刷できるもの」として請求書も納品書も同じコードで処理できる——これがポリモーフィズムです。テストの際にモックオブジェクトへ差し替えられるという利点もあります。
例外クラス
ABAPオブジェクトでは、例外もクラスとして扱います。従来のEXCEPTIONS(sy-subrcで判定)より、はるかに詳細な情報を伝えられます。
" 例外の送出
METHOD get_customer.
SELECT SINGLE * FROM kna1 INTO @DATA(ls_kna1)
WHERE kunnr = @iv_kunnr.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE zcx_customer_not_found
EXPORTING customer_id = iv_kunnr.
ENDIF.
ENDMETHOD.
" 例外の捕捉
TRY.
DATA(ls_customer) = lo_service->get_customer( '0000001000' ).
CATCH zcx_customer_not_found INTO DATA(lx_notfound).
MESSAGE lx_notfound->get_text( ) TYPE 'E'.
CATCH cx_root INTO DATA(lx_root).
" 想定外のエラー
MESSAGE lx_root->get_text( ) TYPE 'E'.
CLEANUP.
" 例外発生時の後始末
ENDTRY.| クラス | 性質 |
|---|---|
| CX_STATIC_CHECK | 宣言必須。呼び出し元が必ず処理する |
| CX_DYNAMIC_CHECK | 宣言不要。実行時にチェック |
| CX_NO_CHECK | 宣言も捕捉も不要。致命的エラー向け |