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

インタフェースの定義

Objective

After completing this lesson, you will be able to インタフェースを定義します。

インタフェースの定義

インタフェースを使用する理由

インタフェースでは、1 つ以上のクラスをプログラムで処理する方法を定義できます。クラスの場合と同様に、インタフェースでは、メソッド、属性、データ型、定数を定義することができます。これらのコンポーネントは、クライアントプログラムが該当のオブジェクトをどのように操作できるのかを記述します。ただし、インタフェースはインスタンス化できません。インタフェースにはメソッドの実装を保持できません。コンセプトを機能させるには、インタフェースを実装する 1 つまたは複数のクラスも必要になります。つまり、独自のクラス宣言にインタフェースが含まれます。また、インタフェースで宣言されたコンポーネントはクラス自身の一部分になります。インタフェースにメソッド宣言が含まれている場合、インタフェースを実装するクラスもそのメソッドの実装を提供する必要があります。

インタフェースには 2 つの重要な用途があります。

異なるクラスに対する統一アプローチの提供: 継承によって関連しないクラスがあるものの、ユーザに共通サービスを提供する必要がある場合は、インタフェースで共通サービスを定義することができます。そうすると、特定のタスクを実行するために、同じ名前と同じ署名を持つメソッドが各クラスによって提供されます。これらのクラスを使用するプログラムは、どのクラスを実際に処理しているのかに関係なく、単一の方法で特定の関数を呼び出すことができます。

複雑なクラスに対する簡易アプローチの提供: 後で説明するように、インタフェースではオブジェクトの制限付きビューが提供されます。これにより、プログラムで実際に必要とされる機能に基づいて特定のクラスを使用するプログラムに、特定のメソッドセットを公開することができます。

インタフェースの動作については、以下の例を参照してください。

インタフェースの定義

インタフェースの定義は、クラスの定義セクションとよく似ています。ただし、インタフェースには実装が保持されないため、INTERFACE 命令には DEFINITION オプションがありません。2 番目の主要な違いは、インタフェースのすべてのコンポーネントはパブリックであるため、インタフェースには可視性セクションがないことです。インタフェースは他のクラスとのインタラクションの観点で有用であるため、パブリックでないコンポーネントを持つことには意味がありません。

インタフェースの定義では、データ型、属性、定数、メソッドを使用できます。インスタンスと静的コンポーネントの両方が許可されます。インタフェースのメソッドには定義がありますが、実装はないことに留意してください。実装クラスによってメソッドが実装されます。

多くの点で、インタフェースは抽象スーパークラスに似ています。継承が存在しない (つまり、明確な "is a" 関係がない) 複数のクラスに対して共通のコンポーネントを定義する必要がある場合には、インタフェースが有用な技法になります。

インタフェースの実装

クラスにインタフェースを実装するには、INTERFACES 命令を使用します。インタフェースのすべてのコンポーネントはパブリックであり、既存のコンポーネントの可視性を変更できないため、クラスのパブリックセクションにインタフェースを記述する必要があります。

INTERFACES 命令が書き込まれると即座に、プログラムの構文が不正になります。その理由は、まだ実装されていないメソッドがインタフェースに含まれているためです。クイックフィックス (Ctrl + 1) を使用して、メソッド実装をクラスに追加することができます。

クラスでインタフェースを宣言する場合は、そのすべてのメソッドを実装する必要があります。

クラスの実装では、インタフェースで宣言されているすべてのメソッドを実装する必要があります。実装でメソッドに名前を付ける場合は、インタフェース名とチルダで結合されたメソッド名で構成される完全修飾名を使用する必要があります。その理由は、メソッド名だけでは一意になる保証がないためです。コンポーネント名は、そのコンポーネントが宣言されたインタフェース内またはクラス内のみで一意であれば十分であることに留意してください。その結果、クラスは get_partner_attributes というメソッドとインタフェース lif_partner を宣言することができます。

試行: インタフェース定義

  1. インタフェース IF_OO_ADT_CLASSRUN を実装する新しいクラスを登録します。
  2. Local Types タブに切り替えて、以下のコードスニペットをエディタにコピーします。
    Code Snippet
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
    INTERFACE lif_partner. METHODS get_partner_attributes. ENDINTERFACE. CLASS lcl_travel_Agency DEFINITION. PUBLIC SECTION. ENDCLASS. CLASS lcl_airline DEFINITION. PUBLIC SECTION. INTERFACES lif_Partner. TYPES: BEGIN OF ts_detail, name TYPE string, value TYPE string, END OF ts_detail, tt_Details TYPE SORTED TABLE OF ts_detail WITH UNIQUE KEY name. METHODS get_details RETURNING VALUE(rt_details) TYPE tt_details. ENDCLASS. CLASS lcl_car_Rental DEFINITION. PUBLIC SECTION. interfaces lif_Partner. TYPES: BEGIN OF ts_info, name TYPE c LENGTH 20, value TYPE c LENGTH 20, END OF ts_info, tt_Info TYPE SORTED TABLE OF ts_info WITH UNIQUE KEY name. METHODS get_information RETURNING VALUE(rt_details) TYPE tt_info. ENDCLASS. CLASS lcl_airline IMPLEMENTATION. METHOD get_details. ENDMETHOD. METHOD lif_partner~get_partner_attributes. ENDMETHOD. ENDCLASS. CLASS lcl_car_rental IMPLEMENTATION. METHOD get_information. ENDMETHOD. METHOD lif_partner~get_partner_attributes. ENDMETHOD. ENDCLASS.
  3. Ctrl + F3 を押してクラスを有効化します。
  4. コードをよく理解してください。

    注記

    この例には実行可能コードはありません。

インタフェースの定義と実装

ローカルクラス LCL_CARRIER のメソッド GET_OUTPUT とローカルクラス LCL_FLIGHT のメソッド GET_DESCRIPTION は非常に類似していることがわかります。定義を調整するには、インタフェースを導入し、両方のクラスに実装します。

テンプレート:

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

ソリューション:

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

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

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

ステップ

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

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

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

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

    4. Next を選択します。

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

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

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

タスク 2: インタフェースの定義

ローカルインタフェース (推奨名: LIF_OUTPUT) を定義し、ローカルクラス LCL_FLIGHT および LCL_CARRIER に実装します。

注記

現時点では、インタフェースは空白のままにします。インタフェースコンポーネントは次のタスクで追加します。

ステップ

  1. グローバルクラスで、ローカルクラス LCL_FLIGHT の定義にナビゲートします。

    1. たとえば、Outline ビューでクラス名を選択します。

  2. public セクションで、存在しないインタフェース LIF_OUTPUT の実装を宣言する文を追加します。

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

      ABAP
      1234
      CLASS lcl_flight DEFINITION ABSTRACT. PUBLIC SECTION. INTERFACES lif_output.
  3. クイックフィックスを使用して、インタフェース LIF_OUTPUT をローカルインタフェースとして登録します。

    1. INTERFACES 命令で、lif_output にカーソルを置き、Ctrl + 1 を押して利用可能なクイックフィックスを呼び出します。

    2. 利用可能なクイックフィックスの一覧から、Create local interface lif_output を選択します。

      結果

      クイックフィックスにより、以下のコードが生成されます。
      ABAP
      123
      INTERFACE lif_output. ENDINTERFACE.
  4. ローカルクラス LCL_CARRIER にも新規インタフェースを実装します。

    1. ローカルクラス LCL_CARRIER の定義にナビゲートします。

    2. PUBLIC SECTION 命令の下に次のコードを追加します。

      ABAP
      1
      INTERFACES lif_output.

タスク 3: インタフェースメソッドの実装

インスタンスメソッド GET_OUTPUT の定義をクラス LCL_CARRIER からインタフェース LIF_OUTPUT に移動します。次に、ローカルクラス LCL_FLIGHT にインタフェースを実装します。ここで、要求をメソッド GET_DESCRIPTION に委任します。

ステップ

  1. クイックフィックスを使用して、メソッド GET_OUTPUT をローカルクラス LCL_CARRIER からローカルインタフェース LIF_OUTPUT に移動します。

    注記

    メソッドがクラスの他のコンポーネントを参照していることを示す警告は無視してください。
    1. ローカルクラス LCL_CARRIER で、インスタンスメソッド GET_OUTPUT の定義にナビゲートします。

    2. METHODS 命令で、get_output にカーソルを置き、Ctrl + 1 を押して利用可能なクイックフィックスを呼び出します。

    3. 利用可能なクイックフィックスの一覧から、Pull-Up get_output to interface lif_output を選択します。

    4. 警告をよく読み、続行を選択します

    結果

    クイックフィックスにより、クラス LCL_CARRIER から GET_OUTPUT メソッドの定義が削除され、メソッドがインタフェースに追加されます。
    ABAP
    1234
    INTERFACE lif_output. METHODS get_output RETURNING VALUE(r_result) TYPE tt_output. ENDINTERFACE.
    さらに、LCL_CARRIER クラスの実装部分のメソッド名は、インタフェースメソッドの完全修飾名に合わせて調整されます。
    ABAP
    123456
    METHOD lif_output~get_output. APPEND |{ 'Carrier Name:'(001) } { me->name }| TO r_result. APPEND |{ 'Passenger Flights:'(002) } { pf_count }| TO r_result. APPEND |{ 'Average free seats:'(003) } { get_average_free_seats( ) }| TO r_result. APPEND |{ 'Cargo Flights:'(004) } { cf_count }| TO r_result. ENDMETHOD.
    最後に、クイックフィックスによって、インタフェースメソッド lif_output~get_output のエイリアス get_output がクラス LCL_CARRIER のパブリックセクションに登録されます。
    ABAP
    1
    ALIASES: get_output FOR lif_output~get_output.
  2. Problems ビューで新しい構文エラーを分析します。

    1. エディタの下にある Problems ビューを開きます。

  3. クイックアシストを使用して、タイプ TT_OUTPUT および T_OUTPUT をローカルクラス LCL_CARRIER からインタフェース LIF_OUTPUT に移動 (プルアップ) します。

    1. ローカルクラス LCL_CARRIER で、タイプ TT_OUTPUT の定義にナビゲートします。

    2. TYPES 命令で、tt_output にカーソルを置き、Ctrl + 1 を押して利用可能なクイックフィックスを呼び出します。

    3. 利用可能なクイックフィックスの一覧から、Pull-Up tt_output to interface lif_output を選択します。

    4. 続行を選択して、タイプ T_OUTPUT に関連する警告を無視します。

    5. 前のステップを繰り返して、タイプ T_OUTPUT をインタフェースにプルアップします。

  4. 必要に応じて、インタフェース定義でタイプ TT_OUTPUT および T_OUTPUT の順序を調整します。

    1. インタフェース定義は以下のようになります。

      ABAP
      12345678
      INTERFACE lif_output. TYPES t_output TYPE string. TYPES tt_output TYPE STANDARD TABLE OF t_output WITH NON-UNIQUE DEFAULT KEY. METHODS get_output RETURNING VALUE(r_result) TYPE tt_output. ENDINTERFACE.
  5. クイックフィックスを使用して、インタフェースメソッド GET_OUTPUT の欠落している実装をローカルクラス LCL_FLIGHT に追加します。

    1. ローカルクラス LCL_FLIGHT の定義にナビゲートします。

    2. INTERFACES 命令で、lif_output にカーソルを合わせ、Ctrl + 1 を押します。または、コード行の左側にある電球が表示されたエラーアイコンを選択します。

    3. クイックフィックスの一覧から、Add implementation for get_output を選択します。

  6. 追加されたメソッド lif_output~get_output で、インスタンスメソッド get_description の呼出を実装し、その結果をリターンパラメータ r_result に格納します。

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

      ABAP
      123
      METHOD lif_output~get_output. r_result = get_description( ). ENDMETHOD.
  7. グローバルクラスをコンソールアプリとして有効化してテストします。

    1. Ctrl + F3 を押します。

    2. F9 を押します。