前の演習問題では、クラス LCL_PASSENGER_FLIGHT および LCL_CARGO_FLIGHT の共通スーパークラス LCL_FLIGHT を登録しました。次に、ローカルクラス LCL_CARRIER を変更して、継承関係を利用します。スーパークラスのデータ型にパラメータとして使用される参照変数を入力し、2 つの個別のインスタンス属性 passenger_flights および cargo_flights の代わりに、乗客または貨物フライトに関係なく、すべてのフライトインスタンスへの参照を保存できる単一のインスタンス属性フライトを定義します。
タスク 1: テンプレートのコピー (オプション)
テンプレートクラス /LRN/CL_S4D401_OOS_INHERITANCE をコピーします。前の演習問題を完了した場合は、このタスクをスキップし、クラス ZCL_##_SOLUTION の編集を続行することができます。
ステップ
クラス /LRN/CL_S4D401_OOS_INHERITANCE を各自のパッケージのクラスにコピーします (推奨名: ZCL_##_SOLUTION、## はグループ番号)。
Project Explorer で、クラス /LRN/CL_S4D401_OOS_INHERITANCE を右クリックしてコンテキストメニューを開きます。
コンテキストメニューから Duplicate.... を選択します。
Package 項目にパッケージの名称を入力します。Name 項目に、ZCL_##_SOLUTION (## はグループ番号) と入力します。
Next を選択します。
移送依頼を確認し、Finish を選択します。
コピーを有効化します。
Ctrl + F3 を押してクラスを有効化します。
タスク 2: 汎用パラメータ
ローカルクラス LCL_CARRIER で、メソッド FIND_PASSENGER_FLIGHT および FIND_CARGO_FLIGHT の定義を調整します。どちらのメソッドでも、ローカルクラス LCL_FLIGHT に基づいて、エクスポートパラメータ e_flight を参照変数として入力します。
ステップ
ローカルクラス LCL_CARRIER で、メソッド FIND_CARGO_FLIGHT の定義を調整します。リターンパラメータ e_flight に LCL_CARGO_FLIGHT ではなく LCL_FLIGHT を入力します。必ず変更を保存してください。
コードを以下のように調整します。
123456789
METHODS find_cargo_flight
IMPORTING
i_airport_from_id TYPE /dmo/airport_from_id
i_airport_to_id TYPE /dmo/airport_to_id
i_from_date TYPE /dmo/flight_date
i_cargo TYPE /lrn/plane_actual_load
EXPORTING
e_flight TYPE REF TO lcl_flight
e_days_later TYPE i.
メソッド FIND_CARGO_FLIGHT の実装で、ローカル変数フライトの使用を分析します。
参照変数 flight のデータ型を照会するには、変数名にカーソルを合わせ、F2 を押します。
グローバルクラスのメソッド IF_OO_ADT_CLASSRUN~MAIN のメソッド FIND_CARGO_FLIGHT の呼出を分析します。
参照変数 cargo_flight のデータ型を表示するには、変数名にカーソルを合わせて F2 を押します。
同様に、メソッド FIND_PASSENGER_FLIGHT の定義を調整します。リターンパラメータ e_flight に LCL_PASSENGER_FLIGHT ではなく LCL_FLIGHT を入力します。
コードを以下のように調整します。
123456789
METHODS find_passenger_flight
IMPORTING
i_airport_from_id TYPE /dmo/airport_from_id
i_airport_to_id TYPE /dmo/airport_to_id
i_from_date TYPE /dmo/flight_date
i_seats TYPE i
EXPORTING
e_flight TYPE REF TO lcl_flight
e_days_later TYPE i.
コードを有効化して、この変更でも構文エラーが発生しないことを確認します。
Ctrl + F3 を押してコードを有効化します。
タスク 3: 一般属性
ローカルクラス LCL_CARRIER で、LCL_PASSENGER_FLIGHT と LCL_CARGO_FLIGHT のインスタンスへの参照を同時に保存できるプライベートインスタンス属性フライトを定義します。CONSTRUCTOR メソッドの実装の属性に、属性 passenger_flights と cargo_flights の組合せコンテンツを入力します。
ステップ
ローカルクラス LCL_FLIGHT で、クイックフィックスを使用して、このクラスに基づくパブリックテーブルデータ型を生成します (テーブルタイプの推奨名: tab)。
ローカルクラス LCL_FLIGHT の定義に移動します。
CLASS 命令で、lcl_flight にカーソルを置き、Ctrl + 1 を押して利用可能なクイックフィックスを呼び出します。
利用可能なクイックフィックスの一覧から、Generate table type for lcl_flight を選択します。
新しい TYPES 命令は以下のようになります。
1
TYPES tab TYPE STANDARD TABLE OF REF TO lcl_flight WITH DEFAULT KEY.
ローカルクラス LCL_CARRIER のプライベートセクションで、新しいインスタンス属性フライトを定義します。ローカルクラス LCL_FLIGHT で登録したテーブルデータ型でデータ型を指定します。
コードを以下のように調整します。
1234
DATA passenger_flights TYPE lcl_passenger_flight=>tt_flights.
DATA cargo_flights TYPE lcl_cargo_flight=>tt_flights.
DATA flights TYPE lcl_flight=>tab.
ローカルクラス LCL_CARRIER のメソッド CONSTRUCTOR の実装を調整します。LCL_PASSENGER_FLIGHT のメソッド GET_FLIGHTS_BY_CARRIER を呼び出した後、passenger_flights に保存されているすべてのオブジェクト参照をフライトに追加します。
ローカルクラス LCL_CARRIER の CONSTRUCTOR メソッドの実装に移動します。
ENDMETHOD 命令の前に、以下のコードを追加します。
123
LOOP AT passenger_flights INTO DATA(passflight).
APPEND passflight TO flights.
ENDLOOP.
テーブル理解が必要な場合は、代わりに以下のコードを追加します。
12345
flights = VALUE #( BASE flights
FOR pflight IN passenger_flights (
pflight
)
).
同様に、cargo_flights にループを実装し、これらの参照をフライトにも追加します。
ENDMETHOD 命令の前に、以下のコードを追加します。
123
LOOP AT cargo_flights INTO DATA(cargoflight).
APPEND cargoflight TO flights.
ENDLOOP.
テーブル理解が必要な場合は、代わりに以下のコードを追加します。
12345
flights = VALUE #( BASE flights
FOR cflight IN cargo_flights (
cflight
)
).
タスク 4: 一般アクセスおよびダウンキャスト
ローカルクラス LCL_CARRIER のインスタンス属性 passenger_flights および cargo_flights を削除し、新しい属性 flights に置き換えます。コードがサブクラスの特定のコンポーネントにアクセスする場合は、ダウンキャストを実装します。
ステップ
ローカルクラス LCL_CARRIER の定義部分で、属性 passenger_flights および cargo_flights の定義を削除またはコメントします。
2 つの DATA 命令を選択し、Ctrl + < を押して各コード行の前にコメント記号を追加します。
CONSTRUCTOR メソッドでは、インライン宣言を使用して passenger_flights および cargo_flights をローカル変数として宣言します。
コードを以下のように調整します。
1234567
DATA(passenger_flights) =
lcl_passenger_flight=>get_flights_by_carrier(
i_carrier_id = i_carrier_id ).
DATA(cargo_flights) =
lcl_cargo_flight=>get_flights_by_carrier(
i_carrier_id = i_carrier_id ).
メソッドがインライン宣言を呼び出した後、プライベートインスタンス属性にローカル変数 passenger_flights の行数を入力します (推奨名: pf_count)。
ヒント
最初に、値割当を実装します。次に、クイックフィックスを使用して属性宣言を登録します。
コードを以下のように調整します。
12345
DATA(passenger_flights) =
lcl_passenger_flight=>get_flights_by_carrier(
i_carrier_id = i_carrier_id ).
pf_count = lines( passenger_flights ).
pf_count にカーソルを置き、Ctrl + 1 を押して Declare attribute pf_count を選択します。
同様に、プライベートインスタンス属性にローカル変数 cargo_flights の行数を入力します (推奨名: cf_count)。
コードを以下のように調整します。
12345
DATA(cargo_flights) =
lcl_cargo_flight=>get_flights_by_carrier(
i_carrier_id = i_carrier_id ).
cf_count = lines( cargo_flights ).
cf_count にカーソルを置き、Ctrl + 1 を押して Declare attribute cf_count を選択します。
メソッド GET_OUTPUT で、組込 LINES 関数を定義した属性に置き換えます。
コードを以下のように調整します。
123456
METHOD 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.
メソッド FIND_CARGO_FLIGHT で、属性 cargo_flights を属性 flights に置き換えます。
コードを以下のように調整します。
12
LOOP AT me->flights INTO DATA(flight)
メソッド GET_FREE_CAPACITY の呼出で、CAST 式を追加します。
コードを以下のように調整します。
1234
IF connection_details-airport_from_id = i_airport_from_id
AND connection_details-airport_to_id = i_airport_to_id
AND CAST lcl_cargo_flight( flight )->get_free_capacity( ) >= i_cargo.
LCL_CARGO_FLIGHT のインスタンスのみを考慮するには、LOOP の WHERE 条件を拡張します。
ヒント
基本行データ型の内部テーブルでは、擬似コンポーネント table_line を使用してコンテンツを指定します。
コードを以下のように調整します。
123
LOOP AT me->flights INTO DATA(flight)
WHERE table_line->flight_date >= i_from_date
AND table_line IS INSTANCE OF lcl_cargo_flight.
同様に、メソッド FIND_PASSENGER_FLIGHT の実装を調整します。
コードを以下のように調整します。
12345678910111213141516171819
LOOP AT me->flights INTO DATA(flight)
WHERE table_line->flight_date >= i_from_date
AND table_line IS INSTANCE OF lcl_passenger_flight.
DATA(connection_details) = flight->get_connection_details( ).
IF connection_details-airport_from_id = i_airport_from_id
AND connection_details-airport_to_id = i_airport_to_id
AND CAST lcl_passenger_flight( flight )->get_free_seats( ) >= i_seats.
DATA(days_later) = flight->flight_date - i_from_date.
IF days_later < e_days_later. e_flight = flight.
e_days_later = days_later.
ENDIF.
ENDIF.
ENDLOOP.
GET_AVERAGE_FREE_SEATS メソッドの実装を調整します。テーブル削減で内部テーブルフライトを使用し、削減に CAST 式と WHERE 条件を追加します。必要な乗客フライト数は、上記で登録した属性 pf_count に保存されます。
コードを以下のように調整します。
12345678910111213141516
METHOD get_average_free_seats.
r_result = REDUCE #(
INIT i = 0
FOR flight IN flights
WHERE ( table_line IS INSTANCE OF lcl_passenger_flight )
NEXT i += CAST lcl_passenger_flight( flight )->get_free_seats( )
) / pf_count.
ENDMETHOD.
グローバルクラスをコンソールアプリとして有効化してテストします。
Ctrl + F3 を押します。
F9 を押します。