コードの分析およびテスト
データ型およびデータ型変換の正しい使用
文字項目の処理
ABAP SQL でのコードプッシュダウンの使用
内部テーブルのパフォーマンスの改善
権限チェックの実装
効果的なオブジェクト指向コードの設計
例外クラスの定義と処理
ABAP コードへの文書の追加

独自の例外クラスの定義

Objective

After completing this lesson, you will be able to 独自の例外クラスを定義します。

独自の例外クラスの定義

すべての名称が cx_sy で始まる事前定義されたシステム例外クラスが多数あります。ただし、これらのクラスは技術エラーを表し、アプリケーションのセマンティックは反映されません。

フライトアプリケーションでは、航空会社と接続番号の特定の組合せが存在しない状況を示す例外が必要になる場合があります。

独自の例外クラスを定義するには、クラス cx_static_check から継承する新規クラスを登録します。

このビデオでは、例外を作成、準備、添付、および発生する方法を学習します。

試行: 独自の例外クラスの定義

例外クラス ZSD4D01_EXCEPTIONS を以下のように登録します。

  1. Ctrl + Shift + N を押して、新しい ABAP リポジトリオブジェクトを作成します。
  2. フィルタテキスト MESSAGE を入力し、該当対象一覧でエントリメッセージクラスをダブルクリックします。
  3. メッセージクラスを有効なパッケージに割り当ててください。名称 ZS4D401_EXCEPTIONS と内容説明を入力し、Next を押します。
  4. 適切な移送依頼を選択し、Finish を選択します。
  5. メッセージ番号 001 を入力し、テキスト接続 &1 &2 は存在しません
  6. メッセージクラスを保存します。
  7. インタフェース IF_OO_ADT_CLASSRUN を実装する新しいクラスを登録します。
  8. Local Types タブに切り替えて、以下のコードスニペットをエディタにペーストします。
    Code Snippet
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
    CLASS lcx_no_connection DEFINITION INHERITING FROM cx_static_Check. PUBLIC SECTION. interfaces if_t100_message. METHODS constructor IMPORTING textid LIKE if_t100_message=>t100key OPTIONAL previous LIKE previous OPTIONAL airlineid TYPE /DMO/CARRIER_ID OPTIONAL connectionnumber TYPE /DMO/CONNECTION_ID OPTIONAL. CONSTANTS: BEGIN OF lcx_no_connection, msgid TYPE symsgid VALUE 'ZS4D401_EXCEPTIONS', msgno TYPE symsgno VALUE '001', attr1 TYPE scx_attrname VALUE 'AIRLINEID', attr2 TYPE scx_attrname VALUE 'CONNECTIONNUMBER', attr3 TYPE scx_attrname VALUE 'attr3', attr4 TYPE scx_attrname VALUE 'attr4', END OF lcx_no_connection. DATA airlineid TYPE /dmo/carrier_id READ-ONLY. DATA connectionnumber TYPE /dmo/connection_id READ-ONLY. ENDCLASS. CLASS lcx_no_Connection IMPLEMENTATION. METHOD constructor. super->constructor( previous = previous ). me->airlineid = airlineid. me->connectionnumber = connectionnumber. CLEAR me->textid. IF textid IS INITIAL. if_t100_message~t100key = lcx_no_connection. ELSE. if_t100_message~t100key = textid. ENDIF. ENDMETHOD. ENDCLASS. CLASS lcl_connection DEFINITION. PUBLIC SECTION. METHODS constructor IMPORTING i_airlineid TYPE /dmo/carrier_id i_connectionnumber TYPE /dmo/connection_id RAISING lcx_no_connection. PRIVATE SECTION. DATA AirlineId TYPE /dmo/carrier_id. DATA ConnectionNumber TYPE /dmo/connection_id. DATA fromAirport TYPE /dmo/airport_from_id. DATA toAirport TYPE /dmo/airport_to_id. ENDCLASS. CLASS lcl_Connection IMPLEMENTATION. METHOD constructor. DATA fromairport TYPE /dmo/airport_from_Id. DATA toairport TYPE /dmo/airport_to_id. SELECT SINGLE FROM /dmo/connection FIELDS airport_from_id, airport_to_id WHERE carrier_id = @i_airlineid AND connection_id = @i_connectionnumber INTO ( @fromairport, @toairport ). IF sy-subrc <> 0. RAISE EXCEPTION TYPE lcx_no_connection EXPORTING airlineid = i_airlineid connectionnumber = i_connectionnumber. ELSE. me->connectionnumber = i_connectionnumber. me->fromairport = fromairport. me->toairport = toairport. ENDIF. ENDMETHOD. ENDCLASS.
  9. Global Class タブに切り替えて、以下のコードスニペットを main( ) メソッドの実装にペーストします。
    Code Snippet
    123456789
    DATA connection TYPE REF TO lcl_connection. DATA exception TYPE REF TO lcx_no_connection. TRY. connection = NEW #( i_airlineid = 'XX' i_connectionnumber = '0000' ). CATCH lcx_no_connection into exception. out->write( exception->get_text( ) ). ENDTRY.
  10. Ctrl + F3 を押してクラスを有効化します。
  11. F9 を押してクラスを実行します。ソースコードを試して理解します。

例外クラスの定義および使用

例外テキストがアプリケーションに対して十分に具体的ではないことが判明しました。そのため、独自の例外クラスを定義し、それをコードで使用します。

テンプレート:

  • /LRN/CL_S4D401_EXS_HANDLING (グローバルクラス)

ソリューション:

  • /LRN/CL_S4D401_EXS_CLASS (グローバルクラス)
  • /LRN/S4D401_EXS_MESS (メッセージクラス)
  • /LRN/CX_S4D401_EXS_FAILED (グローバル例外クラス)

タスク 1: テンプレートのコピー (オプション)

テンプレートクラス /LRN/CL_S4D401_EXS_HANDLING をコピーします。前の演習問題を完了した場合は、このタスクをスキップし、クラス ZCL_##_SOLUTION の編集を続行することができます。

ステップ

  1. クラス /LRN/CL_S4D401_EXS_HANDLING を独自のパッケージのクラスにコピーします (推奨名: ZCL_##_SOLUTION、## はグループ番号)。

    1. Project Explorer で、クラス /LRN/CL_S4D401_EXS_HANDLING を右クリックしてコンテキストメニューを開きます。

    2. コンテキストメニューから Duplicate.... を選択します。

    3. Package 項目にパッケージの名称を入力します。Name 項目に、ZCL_##_SOLUTION (## はグループ番号) と入力します。

    4. Next を選択します。

    5. 移送依頼を確認し、Finish を選択します。

  2. コピーを有効化します。

    1. Ctrl + F3 を押してクラスを有効化します。

タスク 2: メッセージクラスの登録

新しいメッセージクラスを登録します (推奨名: Z##_MESSAGES## は各自のグループ番号)。2 つのメッセージテキストを定義します。1 つは存在しない運送業者をレポートし、もう 1 つは不足している読込権限を報告します。両方のメッセージで、運送業者 ID のプレースホルダを使用します。

ステップ

  1. 新しいメッセージクラスを登録します (推奨名: Z##_MESSAGES## は各自のグループ番号)。

    1. Project Explorer で、パッケージを右クリックし、NewOther ABAP Repository Object を選択します。

    2. 検索項目に、メッセージと入力します。

    3. 検索結果から、テキストメッセージクラスを選択し、を選択します。

    4. Package 項目にパッケージ名が含まれていることを確認します。

    5. Name 項目に、Z##_MESSAGES (## はグループ番号) と入力します。

    6. 内容説明項目に、例外クラスのメッセージと入力します。

    7. Next を選択します。

    8. 移送依頼を確認し、Finish を選択します。

  2. 運送業者が存在しないことを通知するメッセージを定義します (推奨番号: 010)。運送業者 ID のプレースホルダを使用します。

    1. 最初の行の番号列で、 <新規値を入力> を選択し、010 を入力します。

    2. 同じ行のテキスト (短) 列に、運送業者 &1 は存在しませんと入力します。

  3. ユーザに特定の航空会社を照会する権限がないことを通知するメッセージを定義します (推奨番号: 020)。運送業者 ID のプレースホルダを使用します。

    1. 2 行目で、番号列に <新規値を入力> を選択し、020 を入力します。

    2. 同じ行のテキスト (短) 列に、運送業者 &1 を照会する権限がありませんと入力します。

  4. メッセージクラスを保存します。

    注記

    メッセージクラスを有効化する必要はなく、有効化することもできません。メッセージクラスでは、有効バージョンと無効バージョンは区別されません。
    1. Ctrl + S を押して、メッセージクラスを保存します。

タスク 3: 例外クラス登録

スーパークラス CX_STATIC_CHECK から継承する新しいグローバル例外クラス (推奨名: ZCX_##_FAILED## は各自のグループ番号) を登録します。登録したメッセージテキストを参照する 2 つのテキスト ID 定数を定義します。パブリックで読込専用のインスタンス属性 (推奨名: CARRIER_ID) を宣言し、実行時にメッセージ内のプレースホルダがこの属性の値に置き換えられていることを確認します。最後に、オプションのインポートパラメータを使用して CONSTRUCTOR メソッドを拡張し、新規属性を設定します。

ステップ

  1. スーパークラス CX_STATIC_CHECK から継承する新しいグローバルクラスを登録します (推奨名: ZCX_##_FAILED## は各自のグループ番号)。

    1. Project Explorer で、パッケージを右クリックし、NewABAP Class を選択します。

    2. Package 項目にパッケージ名が含まれていることを確認します。

    3. 名称項目に、ZCX_##_FAILED (## はグループ番号) と入力します。

    4. Description 項目に Instantiation Failed と入力します。

    5. Superclass 項目に CX_STATIC_CHECK と入力します。

    6. Next を選択します。

    7. 移送依頼を確認し、Finish を選択します。

  2. コード完了を使用して、新しいテキスト ID 定数 (つまり、パブリック構造化定数) を定義します。

    1. 例外クラスの public セクションで、INTERFACES 命令の後に text を入力し、Ctrl + Space を押してコード完了を呼び出します。

    2. 候補リストから、textIDExceptionClass - 例外クラスのデフォルトテキスト ID を選択します。

    3. コード完了により、コードが以下のように調整されます。

      ABAP
      12345678910111213
      PUBLIC SECTION. INTERFACES if_t100_message. INTERFACES if_t100_dyn_msg. CONSTANTS: BEGIN OF zcx_##_failed, msgid TYPE symsgid VALUE 'msgid', msgno TYPE symsgno VALUE 'msgno', attr1 TYPE scx_attrname VALUE 'attr1', attr2 TYPE scx_attrname VALUE 'attr2', attr3 TYPE scx_attrname VALUE 'attr3', attr4 TYPE scx_attrname VALUE 'attr4', END OF zcx_##_failed.
  3. クイックフィックスを使用して、定数の名前を変更します (推奨名: carrier_not_exist)。

    1. BEGIN OF の後、zcx_##_failed (## は各自のグループ番号) にカーソルを置き、Ctrl + 1 を押して利用可能なクイックフィックスを呼び出します。

    2. 利用可能なクイックフィックスの一覧から Rename zcx_##_failed を選択します。

    3. 定数の名称が強調表示されている間は、新しい名称を入力します。

  4. 定数のコンポーネント値を調整します。メッセージクラスの名称と、最初のメッセージの番号を値として使用します。

    1. コードを以下のように調整します。

      ABAP
      123456789
      CONSTANTS: BEGIN OF carrier_not_exist, msgid TYPE symsgid VALUE 'Z##_MESSAGES', msgno TYPE symsgno VALUE '010', attr1 TYPE scx_attrname VALUE 'attr1', attr2 TYPE scx_attrname VALUE 'attr2', attr3 TYPE scx_attrname VALUE 'attr3', attr4 TYPE scx_attrname VALUE 'attr4', END OF carrier_not_exist.
  5. 同じコードテンプレートおよびクイックフィックスを使用して、2 番目のメッセージテキストに別のテキスト ID 定数を定義します (推奨名: carrier_no_read_auth)。

    1. 以下のコードを追加します。

      ABAP
      123456789
      CONSTANTS: BEGIN OF carrier_no_read_auth, msgid TYPE symsgid VALUE 'Z##_MESSAGES', msgno TYPE symsgno VALUE '020', attr1 TYPE scx_attrname VALUE 'attr1', attr2 TYPE scx_attrname VALUE 'attr2', attr3 TYPE scx_attrname VALUE 'attr3', attr4 TYPE scx_attrname VALUE 'attr4', END OF carrier_no_read_auth.
  6. タイプ /DMO/CARRIER_ID のパブリックの読込専用インスタンス属性を定義します (推奨名: CARRIER_ID)。

    1. 例外クラスのパブリックセクションで、以下のコードを追加します。

      ABAP
      1
      DATA carrier_id TYPE /dmo/carrier_id READ-ONLY.
  7. テキスト ID 定数を調整します。コンポーネント attr1 の値として、新規属性の名称を使用します。

    1. コードを以下のように調整します。

      ABAP
      12345678910111213141516171819
      CONSTANTS: BEGIN OF carrier_not_exist, msgid TYPE symsgid VALUE 'Z##_MESSAGES', msgno TYPE symsgno VALUE '010', attr1 TYPE scx_attrname VALUE 'carrier_id', attr2 TYPE scx_attrname VALUE 'attr2', attr3 TYPE scx_attrname VALUE 'attr3', attr4 TYPE scx_attrname VALUE 'attr4', END OF carrier_not_exist. CONSTANTS: BEGIN OF carrier_no_read_auth, msgid TYPE symsgid VALUE 'Z##_MESSAGES', msgno TYPE symsgno VALUE '020', attr1 TYPE scx_attrname VALUE 'carrier_id', attr2 TYPE scx_attrname VALUE 'attr2', attr3 TYPE scx_attrname VALUE 'attr3', attr4 TYPE scx_attrname VALUE 'attr4', END OF carrier_no_read_auth.
  8. CONSTRUCTOR メソッドの署名を拡張します。属性 carrier_id の値の設定に使用できるオプションのインポートパラメータを追加します (推奨名: carrier_id)。

    1. コードを以下のように調整します。

      ABAP
      12345
      METHODS constructor IMPORTING !textid LIKE if_t100_message=>t100key OPTIONAL !previous LIKE previous OPTIONAL carrier_id LIKE carrier_id OPTIONAL.

      注記

      感嘆符 (!) を無視または削除することができます。既存のパラメータ名の前に配置します。パラメータ名が ABAP キーワードと区別可能である限り、これらはオプションです。グローバルクラスでは、デフォルトで挿入されます。
  9. CONSTRUCTOR メソッドの実装を調整します。メソッドの最後に、オプションのパラメータ carrier_id が初期値であるかどうかをチェックします。初期値でない場合は、その値をインスタンス属性 carrier_id に保存します。

    注記

    インポートパラメータと属性に同じ名称を選択する場合は、自己参照 me を使用して属性を指定する必要があります。
    1. コードを以下のように調整します。

      ABAP
      12345678910
      IF textid IS INITIAL. if_t100_message~t100key = if_t100_message=>default_textid. ELSE. if_t100_message~t100key = textid. ENDIF. IF carrier_id IS NOT INITIAL. me->carrier_id = carrier_id. ENDIF. ENDMETHOD.
  10. 例外クラスを有効化します。

    1. Ctrl + F3 を押してコードを有効化します。

タスク 4: 例外クラスの使用

ローカルクラス LCL_CARRIER のメソッド GET_INSTANCE で、例外クラス CX_ABAP_INVALID_VALUE および CX_ABAP_AUTH_CHECK_EXCEPTION を独自の例外クラスに置き換えます。警告に従って、メソッド IF_OO_ADT_CLASSRUN~MAIN でメソッド定義および例外処理の RAISING 句を調整します。

ステップ

  1. ローカルクラス LCL_CARRIER のメソッド GET_INSTANCE の実装にナビゲートします。

    1. たとえば、Outline ビューで ZCL_##_SOLUTIONLCL_CARRIER を展開し、GET_INSTANCE を選択します。

  2. 例外クラス CX_ABAP_INVALID_VALUE を使用する RAISE EXCEPTION 命令を削除するか、またはコメントしてください。

    1. パラメータ受渡しを含む RAISE EXCPETION 命令を選択し、Ctrl + < を押して選択した行の前にコメント記号を追加します。

  3. 独自の例外クラスを使用して RAISE EXCEPTION 命令を実装します。コード完了を使用して、CONSTRUCTOR の完全な署名を挿入します。

    1. コメントされたコードの後にカーソルを置き、例外発生タイプ ZCX_## (## は各自のグループ番号) を入力します。

    2. Ctrl + Space を押して、コード完了を呼び出します。

    3. Shift + Enter を押して、完全な署名を挿入します。

    4. コード完了に以下のコードが追加されていることを確認します。

      ABAP
      12345
      RAISE EXCEPTION TYPE zcx_##_failed * EXPORTING * textid = * previous = * carrier_id =
  4. オプションの textid パラメータにテキスト ID 定数の 1 番目を指定し、オプションの carrier_id パラメータに i_carrier_id の値を指定します。

    1. コードを以下のように調整します。

      ABAP
      12345
      RAISE EXCEPTION TYPE zcx_##_failed EXPORTING textid = zcx_##_failed=>carrier_not_exist * previous = carrier_id = i_carrier_id.
  5. 同様に、2 番目の RAISE EXCEPTION 命令で独自の例外クラスを使用します。今回は、パラメータ textid の入力として他のテキスト ID 定数を使用します。

    1. コードを以下のように調整します。

      ABAP
      123456789
      * RAISE EXCEPTION TYPE cx_abap_auth_check_exception * EXPORTING * textid = cx_abap_auth_check_exception=>missing_authorization. RAISE EXCEPTION TYPE zcx_##_failed EXPORTING textid = zcx_##_failed=>carrier_no_read_auth * previous = carrier_id = i_carrier_id.
  6. クイックフィックスを使用して、メソッド GET_INSTANCE の RAISING 句に独自の例外クラスを追加します。

    1. 2 つの RAISE EXCEPTION 命令のいずれかを含むコード行に移動し、左側の電球を含む警告アイコンを選択して、利用可能なクイックフィックスを呼び出します。

    2. 利用可能なクイックフィックスの一覧から、Add raising declaration を選択します。

  7. メソッド GET_INSTANCE の RAISING 句から冗長な例外を削除またはコメントします。

    1. コードを以下のように調整します。

      ABAP
      123456789
      CLASS-METHODS get_instance IMPORTING i_carrier_id TYPE /dmo/carrier_id RETURNING VALUE(r_result) TYPE REF TO lcl_carrier RAISING * cx_abap_invalid_value * cx_abap_auth_check_exception zcx_##_failed.
  8. メソッド IF_OO_ADT_CLASSRUN~MAIN で例外処理を調整します。2 つの CATCH ブロックを、独自の例外クラスに対して 1 つの CATCH ブロックに置き換えます。

    1. コードを以下のように調整します。

    ABAP
    12345678910111213
    TRY. DATA(carrier) = lcl_carrier=>get_instance( i_carrier_id = c_carrier_id ). out->write( name = `Carrier Overview` data = carrier->get_output( ) ). * CATCH cx_abap_invalid_value INTO DATA(exc_inv). * out->write( exc_inv->get_text( ) ). * CATCH cx_abap_auth_check_exception INTO DATA(exc_auth). * out->write( exc_auth->get_text( ) ). CATCH zcx_##_failed INTO DATA(exc_fail). out->write( exc_fail->get_text( ) ). ENDTRY.
  9. コードを有効化してテストします。定数 c_carrier_id の値を調整して、さまざまな例外を発生させます。

    1. Ctrl + F3 を押してコードを有効化します。

    2. F9 を押して、コードをコンソールアプリとして実行します。

    3. 定数 c_carrier_id の値を XX に設定して、無効な値の例外を発生させます。

    4. 定数 c_carrier_id の値を UA に設定して、権限不足の例外を発生させます。