今回は、オブジェクト指向言語での開発を行うときに必要となる基礎知識として、クラスの継承やインターフェースの利用などを説明します。
メソッドの実装だけであれば構造化思考と変わりませんが、オブジェクト指向での開発となると継承、上書きなどを意識する必要が出てきます。
それらの機能の利用方法を利点も併せて説明していきます。
クラスのみでの実装
以下のようなテーブルに各商品の情報が入っています。
これらの商品の売価の一覧を取得するロジックを考えてみましょう。
各商品ごとに売価の取得方法が異なります。
商品ごとのクラスを用意し、それぞれに必要なロジックを実装します。
テーブルの各データからクラスインスタンスを作り、get商品名、get売価メソッドを利用して一覧を作成します。
しかし、クラスが異なるため同じリストにまとめることはできません。
各行で商品種別ごとに表示対象を切り替えることが必要になります。
親クラスの利用
先ほどのクラスの親クラスを以下のように作成します。
医薬品クラス、設備レンタルクラスのget商品名は親クラスで実装されているので各クラスでの実装は不要となっています。
駐車場クラスのみ処理内容が異なるため上書き実装を行っています。
get売価については実装が必須のため、各クラスでそれぞれ必要なロジックを実装しています。
このような構造にすることで、各クラスを親クラスにキャストすることで一つのリストに入れることができます。
行ごとに分岐する必要もなく、get商品名、get売価で異なったロジックを呼ぶことができるのでプログラム品質が向上します。
今回は一つのリストにまとめるためのクラスキャストを例に説明しましたが、画面のイベント処理などで共通して処理する部分は親クラスで実装し、各画面特有の処理は子クラスで実装するなどの使い方ができます。
クラス継承は以下のようなイメージで動作します。
get商品コードは駐車場クラスでは実装されていませんので、親クラスのロジックが実行されます。
get商品名メソッドは親クラスにも駐車場クラスにも実装されています。
この場合、駐車場クラスで上書いたということになりますので、駐車場クラスで実装したろぎっくが実行されます。
get売価メソッドは親クラスでAbstractとして宣言されています。
Abstractメソッドは親クラスでは実装できず、子クラスで実装が必須のメソッドとなります。
get売価メソッドを実行すると、駐車場クラスで実装されたロジックが実行されます。
get地名メソッドは親クラスでは実装されていません。
子クラスでは親クラスに実装されていないメソッドを実装することができます。
子クラスは親クラスにキャストすることができます。
キャストした場合でも各メソッドを呼び出すことができます。
get商品名メソッドのように親クラスにも子クラスにも実装されているメソッドについては子クラス(インスタンスを生成したときのクラス)のロジックが実行されます。
ただし、get地名メソッドのように、親クラスに宣言されていないメソッドを呼び出すことはできません。
インターフェース
以下のような仕入れ品のテーブルがあり、医薬品テーブルと仕入れ品テーブルの商品名の一覧を作成することを考えてみましょう。
以下のようなクラスを作成しました。
このクラスは売価がなく、ほかのクラスと機能が異なるため親クラスを継承していません。
そのため先ほどの売価一覧のように親クラスにキャストして一覧を作成することができません。
そこでインターフェースを使用して同じ型にキャストできるようにします。
このようなクラス構成にすることで以下のようにキャストすることができます。
クラス継承は一つの親クラスしかできませんが、インターフェースは複数のインターフェースを実装することができます。
また、親クラスが実装しているインターフェースは子クラスからキャストすることが可能です。
インターフェースは共通メソッドの引数などで使用することで、継承元が異なるクラスで同じ処理を実行するときなどで利用します。
インスタンスの参照
親クラス、子クラス、インターフェースについての使い方はイメージできたと思います。
実際にプログラムを作成して実行したときのメモリ内の構造はどのようになるのでしょうか。
医薬品クラス c1 = new 子クラス();
親クラス p1 = (親クラス)c1;
商品名インターフェース i1 = (商品名インターフェース)c1;
上記のようなプログラムを作成、実行したときのメモリ内の構造は以下のようになります。
1行目で医薬品クラスのインスタンスを生成しますが、この時にアドレス&M5に配置されます。
2行目、3行目で親クラスと商品名インターフェースの変数にキャストして代入していますが、
変数としては同じアドレスの&M5が設定されるため、p1、i1は医薬品クラスのインスタンスを参照します。
このような構造となっているため、p1、i1のメソッドの呼び出しやデータの参照を行うと、医薬品クラスインスタンスのメソッドやデータが取得されるのです。