Javaのオブジェクト指向のひとつ、ポリモーフィズムについての練習問題です。
こちらも初学者向けに作られた(受講した講座に出てきた)問題を記載しますので読者の参考になれば幸いです。
(環境:Mac・Eclipse_2020-12を使用しています。)
ポリモーフィズム応用Level_1とLevel_2に分けて問題を記載します。
今回はLevel_1の問題です。
問題文(仕様書)に従ってコードを書いていくと解ける問題かと思います。
注意:問題の回答は、私なりの回答となっています。正解でない場合もあると思いますのでご了承ください。。
1.ポリモーフィズム応用問題・Level_1(チケットの発券)
下記の仕様書に従って、プログラムを作成しなさい。
※仕様書の中で不足箇所があると判断した場合は、変更・追加して良い事とする。
インターフェース一覧
| 修飾子 | 名前 | 説明 |
| public | MealTicket | 食券 |
クラス一覧
| 修飾子 | 名前 | 説明 |
| public | CurryTicket | カレーの食券(MealTicket の実装クラス) |
| public | SushiTicket | 寿司の食券(MealTicket の実装クラス) |
| public | RamenTicket | ラーメンの食券(MealTicket の実装クラス) |
| public | MealTicketFactory | MealTicket 実装クラスのインスタンスを生成する |
| public | MealTicketMain | MealTicket を利用する |
〇MealTicket インターフェース
【メソッド】
| 修飾子 | 戻り値の型 | 名前 | 引数 | 説明 |
| public | void | ticketing | なし | 食券を発券する(抽象メソッド) |
〇CurryTicket クラス(MealTicket を実装する)
【メソッド】
| 修飾子 | 戻り値の型 | 名前 | 引数 | 説明 |
| public | void | ticketing | なし | カレーの食券を発券します。と表示する。 |
〇SushiTicket クラス(MealTicket を実装する)
【メソッド】
| 修飾子 | 戻り値の型 | 名前 | 引数 | 説明 |
| public | void | ticketing | なし | 寿司の食券を発券します。と表示する。 |
〇RamenTicket クラス(MealTicket を実装する)
【メソッド】
| 修飾子 | 戻り値の型 | 名前 | 引数 | 説明 |
| public | void | ticketing | なし | ラーメンの食券を発券します。と表示する。 |
〇MealTicketFactory クラス
【メソッド】
| 修飾子 | 戻り値の型 | 名前 | 引数 | 説明 |
| public | MealTicket | choiceMeal | int num | num が1ならば CurryTicket のインスタンス、2ならば SushiTicket のインスタンス、3ならば RamenTicket のインスタンス、それ以外ならば『有効な整数を入力してください』の表示を返す。 |
〇MealTicketFactoryMain クラス
【mainメソッド】
1.標準入力から整数を入力する。
2.MealTicketFactory のインスタンスを生成する。
3.インスタンスの choiceMeal メソッド(引数は1.の入力値)を呼び出し、その戻り値をMealTicket 型の変数に代入する。
4. 3.の変数の ticketing メソッドを呼び出す。
【表示例:1】
メニューの番号を入力してください。
1:カレー
2:寿司
3:ラーメン
1
カレーの食券を発券します。
【表示例:1】
メニューの番号を入力してください。
1:カレー
2:寿司
3:ラーメン
1
カレーの食券を発券します。
【表示例:2】
メニューの番号を入力してください。
1:カレー
2:寿司
3:ラーメン
5
有効の整数を入力してください
Exception in thread “main” java.lang.NullPointerException
at test/Foodvoucher.MealTicketMain.main(MealTicketMain.java:18)
※エラーメッセージが出るのはこの時点ではOK。Level_2の問題にて解決します。
2.回答例
・MealTicket(インターフェース)クラス
interface MealTicket {
void ticketing() ;
}
・CurryTicket クラス
public class CurryTicket implements MealTicket{
@Override
public void ticketing() {
System.out.println("ラーメンの食券を発券します。");
}
}
・SushiTicket クラス
public class SushiTicket implements MealTicket{
@Override
public void ticketing() {
System.out.println("寿司の食券を発券します。");
}
}
・RamenTicket クラス
public class RamenTicket implements MealTicket{
@Override
public void ticketing() {
System.out.println("ラーメンの食券を発券します。");
}
}
・MealTicketFactory クラス
public class MealTicketFactory {
public MealTicket choiceMeal(int num) {
MealTicket mealticket = null;
if(num == 1) {
mealticket = new CurryTicket();
}else if(num == 2) {
mealticket = new SushiTicket();
}else if(num == 3) {
mealticket = new RamenTicket();
}else {
System.out.println("有効の整数を入力してください");
}
return mealticket;
}
}
・MealTicketMain クラス
import java.util.Scanner;
public class MealTicketMain {
public static void main(String[] args) {
System.out.println("メニューの番号を入力してください");
System.out.println("1:カレー");
System.out.println("2:ラーメン");
System.out.println("3:寿司");
Scanner scan = new Scanner(System.in);
int ticket_num = scan.nextInt();
//MealTicketFactoryのインスタンスの生成
MealTicketFactory factory = new MealTicketFactory();
//choiceMealメソッドを呼び出してMealTicketの変数に代入している。
//factory.choiceMeal(ticket_num);
//MealTicketの変数(親クラス)に代入する
MealTicket MealTicket = factory.choiceMeal(ticket_num);
MealTicket.ticketing();
scan.close();
}
}
3.解説
実は、今回もあまり回答に自信がありません・・・(泣
もしより良い回答ができる方がいらっしゃれば、コメントに記載していただけると非常に嬉しいです!
それでは、一旦解説いたします。
・MealTicket(インターフェース)クラスについて
指示書(問題文)にインターフェースの記載がありますので、インターフェースを実装するのクラスを作成しています。
メソッドの具体的な処理内容を記述せず、変数とメソッドの型のみを定義しています。
void ticketing() ;
・CurryTicket、SushiTicket、RamenTicket クラスについて
指示書(問題文)にある MealTicket の実装を行う必要があります。
インターフェースを実装するクラスには、 implements 記載してインターフェースを指定します。
public class クラス名 implements MealTicket{}
次にインターフェースで定義しているメソッドも実装させています。
public void ticketing() {
@Override
System.out.println("〇〇〇 の食券を発券します。");
}
・MealTicketFactory クラスについて
指示書(問題文)の説明に記載されている内容を実装する為に if-else if文を利用しました。
そして、戻り値の型が MealTicket とクラス型をしている事とインスタンスを格納して返すために変数 mealticket を定義しました。
MealTicket mealticket = null;
null を指定しているのは、個人的に初期値を設定する事を癖にしているだけですので『MealTicket mealticket ;』としても大丈夫です。
不要の説明かもしれませんが、インターフェースはインスタンスを作成できませんので『MealTicketを new する』と記載する事は出来ません。
また、定数をしていて変数を格納する事は可能です。
・MealTicketMain クラスについて
メインクラスは、指示書通りに記載していくとコードが完成出来ると思います。
その中で私がつまづいた点を記載したいと思います。
//choiceMealメソッドを呼び出してMealTicketの変数に代入している。
//factory.choiceMeal(ticket_num);
上記の箇所ですが、基本的には記載しなくても良いですが、次の行に記載するコードが読み易くなると思い記載しました。
//MealTicketの変数(親クラス)に代入する
MealTicket MealTicket = factory.choiceMeal(ticket_num);
MealTicket.ticketing();
前述しましたが、インターフェースはインスタンスを生成できませんが、変数を定義する事は可能です。
そして、サブクラス(CurryTicket、SushiTicket、RamenTicket)のインスタンスで取得したデータをスーパークラス(MealTicket)に格納する流れとなっています。
4.まとめ
いかがでしたでしょうか。
インターフェースは、少し特殊なルールがありますがそこまで難しい内容ではないかと思います。
私は、まずコードを書いて使用方法を覚える事を優先して学んでいました。
そして、参考書やYouTubeの解説動画などをじっくり読んで見て理解を深める事をお勧めしたいと思います。
今回の問題が、少しでも読者の方の参考になれば幸いです。

コメント