インターフェースとポリモーフィズム
インターフェースは抽象メソッドで構成され、実装したクラスで具象化(実際の処理を定義)します。そのため、プログラムの仕様を作るように扱うことができます。
例えば、パソコンなどについているUSB(Universal Serial Bus)は規格または仕様であって、何かの部品そのものを指すわけではありません。USBの仕様を実装しているパソコンや、記憶装置、携帯端末などがあります。同じ仕様を実装している物を、つなげていろいろなことができます。
USBを実装しているものはそれぞれ別々に設計され、作られている点に注目してください。パソコンを作るときには、USBを実装している部品を差し込めるようにUSBで規定されているサイズの差込口を用意し、差し込んだ部品からどのようにデータなどを読み書きするかを具体的に設計して、製造します。USBを実装している部品は必ずUSBで規定されているサイズの接続部を持っていて、何らかの処理を行えると仮定してパソコンを設計・製造することができます。
インターフェースも同様に、プログラム上の仕様を策定して、それぞれのクラスで実装させることによって個々のクラスを作りやすくすることができます。
ではこれから、IDripインターフェースを実装したいくつかの種類の飲み物を作ってみましょう。また、IDripインターフェースを実装した飲み物を扱うことのできるドリッパーマシンも作成してみましょう。
○ ファイル
次のようにファイルを作成してください。
ファイル名 | Tea.java |
---|
○ プログラム
IDripインターフェースを実装したTeaクラスを作成してください。
Tea.java
- public class Tea implements IDrip{
- //フィールド
- private String name = "ティー";
- //メソッド
- public String drip(){
- return this.name;
- }
- public String dripWithMilk(){
- return "ミルク" + this.name;
- }
- }
○ クラス図
○ 解説
6~8行目では、IDripインターフェースのdripメソッドをオーバーライドしています。このメソッドはフィールドに設定されている飲み物を返します。今回は紅茶が注がれるイメージとして文字列を返しています。
10~12行目では、IDripインターフェースのdripWithMilkメソッドをオーバーライドしています。このメソッドはミルクとティーを返すことでミルクティーを注ぎます。
○ ファイル
次のようにファイルを作成してください。
ファイル名 | Dripper.java |
---|
○ プログラム
次に、ドリップインターフェースとポリモーフィズムを実装したコーヒークラスを作成しましょう。
Dripper.java
- public class Dripper{
- //フィールド
- private boolean milkflag = false; //ミルクを注ぐ場合:true 注がない場合:false
- //メソッド
- //ミルクを注ぐかどうかを設定するメソッド
- public void setMilkStatus (boolean flag){
- this.milkflag = flag;
- }
- //セットした飲み物を注ぐメソッド
- public String dripDrink(IDrip drink){
- if(milkflag){
- return drink.dripWithMilk();
- }else{
- return drink.drip();
- }
- }
- }
○ クラス図
○ 解説
3行目では、飲み物を注ぐときにミルクも一緒に注ぐかどうかの状態を保持するフィールドが定義されています。7~9行目のメソッドでその状態を設定します。
12~18行目では、飲み物を注ぎます。その時に注ぐ飲み物のオブジェクトを渡すようになっています。ここで注目できるのは引数の型が「IDrip」型であるという点です。この型を実装しているオブジェクトであればセットできます。この仕組みにより、このドリッパーがある特定の飲み物用のものではなく、IDripという仕様を実装している飲み物であればこのドリッパーを使うことができます。このような仕組みのため、ドリッパークラスは具体的にどんな飲み物がセットされるかを意識せずに設計することができるわけです。
○ ファイル
次のようにファイルを作成してください。
ファイル名 | DripperTest.java |
---|
○ プログラム
では次にmainメソッドを記述しましょう。
DripperTest.java
- import java.io.*;
- public class DripperTest {
- public static void main(String[] args) throws Exception{
- //ドリッパーオブジェクトを生成
- Dripper dripper = new Dripper();
- //キーボードを使用する準備
- BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
- while(true){
- //メニューを入力
- System.out.println("飲み物を選んでください。");
- System.out.print("1)珈琲 2)紅茶 9)終了:");
- String drink = br.readLine();
- if(drink.equals("9")){
- //プログラムを終了する
- return;
- }
- System.out.print("ミルクは注ぎますか(Y/N):");
- String milk = br.readLine();
- //ミルクの状態をドリッパーにセットする
- if(milk.equals("Y")){
- dripper.setMilkStatus(true);
- }else if(milk.equals("N")){
- dripper.setMilkStatus(false);
- }
- //入力内容によって分岐する
- String cup = "";
- switch(drink){
- case "1":
- //珈琲を注ぐ
- cup = dripper.dripDrink(new Coffee());
- break;
- case "2":
- //紅茶を注ぐ
- cup = dripper.dripDrink(new Tea());
- break;
- }
- //カップの中身を表示する
- System.out.println("カップには" + cup + "が入っています。");
- }
- }
- }
○ コンパイルと実行
C:¥work>javac DripperTest.java
C:¥work>java DripperTest
飲み物を選んでください。
1)珈琲 2)紅茶 9)終了:1
ミルクは注ぎますか(Y/N):Y
カップにはミルクコーヒー(微糖)が入っています。
飲み物を選んでください。
1)珈琲 2)紅茶 9)終了:1
ミルクは注ぎますか(Y/N):N
カップにはコーヒーが入っています。
飲み物を選んでください。
1)珈琲 2)紅茶 9)終了:2
ミルクは注ぎますか(Y/N):N
カップにはティーが入っています。
飲み物を選んでください。
1)珈琲 2)紅茶 9)終了:2
ミルクは注ぎますか(Y/N):Y
カップにはミルクティーが入っています。
飲み物を選んでください。
1)珈琲 2)紅茶 9)終了:9
C:¥work>
○ 解説
6行目では、ドリッパーオブジェクトを作成しています。その後、メニューを表示して、珈琲か紅茶を選びます。そして、ミルクを注ぐかどうかを入力します。ミルクを注ぐ場合は27行目にある、ドリッパーオブジェクトのsetMilkStatusメソッドにtrueをセットしてミルクを注ぐ準備をさせます。注がない場合は29行目にある、ドリッパーオブジェクトのsetMilkStatusメソッドにfalseをセットしてミルクの設定を解除します。
33行目では、飲み物を注ぐためのカップを用意しています。34~43行目では選択した飲み物に応じて処理を分岐しています。珈琲を選択した場合は、37行目の処理が実行されます。この処理はドリッパーオブジェクトのdripDrinkメソッドを呼び出す時にコーヒーオブジェクトを生成して渡しています。結果として珈琲が注がれます。なお、ミルクを注ぐ準備がされている場合はミルクコーヒーが注がれます。41行目ではティーオブジェクトを生成して、紅茶を注いでいます。そして、46行目でカップの中身を表示しています。