スポンサーリンク

【Java】オブジェクト指向の練習問題Level_3(メニュー注文表)、例外処理(TRY-CATCH)

JAVA練習問題集

Java.オブジェクト指向練習問題Level_2の続きの練習問題Level_3です。
Level_3から挑戦しても大丈夫かと思いますが、難しいと感じた方は練習問題Level_1の記事練習問題Level_2の記事を先にご確認ください。
初学者向けに作られた(受講した講座に出てきた)問題を記載しています。
読者の参考になれば幸いです。
(環境:Mac・Eclipse_2020-12を使用しています。)

Level_1からLevel_3と段階的に難易度を分けて問題を記載しています。

Level_3については、『例外処理(try-catch)』を実装する問題となっています。
そして、練習問題Level_2で作成するクラスを利用して解く問題となっています。

注意:問題の回答は、私なりの回答となっています。正解でない場合もあると思いますのでご了承ください。。

1.オブジェクト指向・問題Level_3(メニュー注文表)

下記の仕様書に従って、プログラムを作成しなさい。
※仕様書の中で不足箇所があると判断した場合は、変更・追加して良い事とする。

(Level_2のプログラムを参考にして)抽象クラスを利用した内容のプログラムを作成しなさい。
また、サイズ選択時に整数以外または1〜3以外の入力があった場合は、再入力を求めるように例外処理を利用してください。

クラス一覧

修飾子クラス名説明
public sbstractAbstractSizeサイズ選択(抽象クラス)
publicHambergerハンバーガーのサイズ選択(AbstractSizeのサブクラス)
publicFrenchFriesポテトのサイズ選択(AbstractSizeのサブクラス)
publicDrinkドリンクのサイズ選択(AbstractSizeのサブクラス)
publicCalc計算
publicOrderMain金額の表示

○AbstractSizeクラス

【フィールド】(getter/setterを作成)

修飾子名前説明
privateStringname商品名

【コンストラクタ】

修飾子引数説明
protectedString nameフィールドに値を代入する

【メソッド】

修飾子戻り値の型名前引数説明
public abstractintselectSizeなし標準入力された値から値段を判別して返す抽象メソッド

○Hamberger、FrenchFries、Drinkクラス

【フィールド】

名前説明
Stringname商品名

【コンストラクタ】

引数説明
Stringフィールドに値を代入する

【メソッド】

戻り値の型名前引数説明
IntselectSizeなし・フイールドの値(商品名)を表示する
・Mainクラスにて、標準入力で1〜3が入力された場合の値を設定し、値から値段を判別して返す(switch文を利用)

○Calcクラス
【メソッド】

戻り値の型名前引数説明
Inttotalint ham
int ff
int dri
注文商品のサイズの金額を引数として受け取り、全て足して合計を返す。

○OrderMainクラス
【mainメソッド】

1、各クラスのインスタンスを生成する(コンストラクタの引数に適当な値を代入する)
2、3つのインスタンスの selectSizeメソッドを呼び出す
3、各フィールドの値と各メソッドの戻り値(商品名と選択肢たサイズの値段)を表示
4、Calc のインスタンスの totalメソッドを呼び出す
5、total メソッドの戻り値を表示する

【表示例】
メニューのサイズを選択してください。
チーズバーガー
1:シングル、2:ダブル、3:トリプル
4
1〜3を入力してください。
1
ポテト
1:S、2:M、3:L
a
1〜3を入力してください。
1
ジンジャーエール
1:S、2:M、3:L
1
[選んだメニュー]
チーズバーガー:240円
ポテト:180円
コーラ:110円
お会計は 530円です。

2.回答例

・OrderMainクラス

public class OrderMain3 {

  public static void main(String[] args) {

	String hamburger = "チーズバーガー";
	System.out.println(hamburger);
	Scanner scan1 = new Scanner(System.in);
	Hamburger2 hb = null;	//スコープ範囲を広げる為の処理
	while (true) {
		try {
			System.out.println("メニューのサイズを選んでください");
			System.out.println("1:シングル、2:ダブル、3:トリプル");
			int hbselect = scan1.nextInt();

			//hbselect が正しい入力の場合
			if (hbselect == 1 || hbselect == 2 || hbselect == 3) {
				hb = new Hamburger2(hamburger, hbselect);
				break; //ループから抜ける。
			}
			//負の数、0、4以上の数字が入力された際の処理
			System.out.println("指定の数字が入力されていません。1〜3を入力してください。");
			continue;

		} catch (InputMismatchException e) {
			//負の数字や文字列を入力された際の処理
			scan1.nextLine();
			System.out.println("入力に誤りがありました。1〜3を入力してください。");
		}
	}
	String frenchfries = "ポテト";
	System.out.println(frenchfries);
	Scanner scan2 = new Scanner(System.in);
	FrenchFries2 frenh = null;   //スコープ範囲を広げる為の処理
	while (true) {
		try {
			System.out.println("1:S、2:M、3:L");
			int ffselect = scan2.nextInt();

			//ffselect が正しい入力の場合
			if (ffselect == 1 || ffselect == 2 || ffselect == 3) {
				frenh = new FrenchFries2(frenchfries, ffselect);
				break; //ループから抜ける。
			}
			//負の数、0、4以上の数字が入力された際の処理
			System.out.println("指定の数字が入力されていません。1〜3を入力してください。");
			continue;
		} catch (InputMismatchException e) {
			//負の数字や文字列を入力された際の処理
			scan2.nextLine();
			System.out.println("入力に誤りがありました。1〜3を入力してください。");
		}
	}

	String drink = "コーラ";
	System.out.println(drink);
	Scanner scan3 = new Scanner(System.in);
	Drink2 dk = null;    //スコープ範囲を広げる為の処理
	while (true) {
		try {
			System.out.println("1:S、2:M、3:L");
			int dkselect = scan3.nextInt();

			//dkselect が正しい入力の場合
			if (dkselect == 1 || dkselect == 2 || dkselect == 3) {
				dk = new Drink2(drink, dkselect);
				break; //ループから抜ける。
			}
			//負の数、0、4以上の数字が入力された際の処理
			System.out.println("指定の数字が入力されていません。1〜3を入力してください。");
			continue;
		} catch (InputMismatchException e) {
			//文字列を入力された際の処理
			scan3.nextLine();
			System.out.println("入力に誤りがありました。1〜3を入力してください。");
		}
	}

	System.out.println("【選んだメニュー】");
	int ham = hb.selectSize();
	hb.namePrintln();

	int ff = frenh.selectSize();
	frenh.namePrintln();

	int dri = dk.selectSize();
	dk.namePrintln();

	Calc calc = new Calc();
	System.out.println("お会計は" + calc.total(ham, ff, dri) + "円です。");

	scan1.close();
	scan2.close();
	scan3.close();
   }
}

・その他クラス

その他クラスについては、Level_2と全て同じ内容(変更箇所はありません。)となっていますのでこちらをごかくにんください。

3.解説

・OrderMainクラスの例外処理

例外処理についての詳しい説明は、比較的読み易いと思ったサイト下記に記載いたします。
宜しければご参考ください。
https://x-tech.pasona.co.jp/media/detail.html?p=9462

まず私は、例外処理をどのクラスに記載するのか?と迷いました。
各クラスで実装する事も考えましたが、メインクラス(プログラムを実行するクラス)で例外処理を実装しました。
理由は、標準入力を行った際にint型を指定しているのにString型を入力してしまうと、変数に代入された段階でエラーが発生する為です。

次に、どの部分をtry-catchで囲むのか?と迷いました。
また、問題文に『再入力を求める』処理と記載がありましたので繰り返し処理も合わせて実装させる必要があります。
色々と試行錯誤(実際に何度もコードを書いては手直しを行いました・・・)しながら、各メニューサイズを入力する箇所(3箇所)に分けて実装する事にしました。

チーズバーガーのサイズ選択箇所をピックアップして解説を進めさせていただきます。

		   String hamburger = "チーズバーガー";
		   System.out.println(hamburger);
		   Scanner scan1 = new Scanner(System.in);
		①Hamburger2 hb = null;		//スコープ範囲を広げる為の処理
		    while (true) {
			try {
				System.out.println("メニューのサイズを選んでください");
				System.out.println("1:シングル、2:ダブル、3:トリプル");
				int hbselect = scan1.nextInt();

				//hbselect が正しい入力の場合
				if (hbselect == 1 || hbselect == 2 || hbselect == 3) {
		②			hb = new Hamburger2(hamburger, hbselect);
		③			break; //ループから抜ける。
				}
				//負の数、0、4以上の数字が入力された際の処理
				System.out.println("指定の数字が入力されていません。1〜3を入力してください。");
		④		continue;

			} catch (InputMismatchException e) {
		⑤		//負の数字や文字列を入力された際の処理
				scan1.nextLine();
				System.out.println("入力に誤りがありました。1〜3を入力してください。");
			}
		}

①の部分ですが、コメントにも記載している通りスコープの範囲を広げる為の処理です。
プログラムの最後に合計金額を求める処理を行いますが、その際に変数『hb』使用する必要があります。
ですが、①の記載がtry-catchの中にあると最後の合計金額を求める処理のスコープ範囲外となる問題が出てしまいます。
そこで、try-catchの外に変数を宣言(初期化)しておく事でこの問題を回避させました。
※例:正しいサイズが入力された際の処理にて、②の箇所の『hb』に格納されたデータが①に渡される事になります。

③の箇所にて、正しいサイズが入力された場合にループ処理から抜け出しています。

④にて、負の数、0、4以上の数字が入力された場合には、またループ処理に戻るcontinueを記載しています。

⑤の箇所は、文字列や例外が発生した際にたどり着きます。
この時、標準入力『scan1.nextLine();』を再度行わせている箇所で注意点があります。
『.nextInt();』から『.nextLine();』に変更している点です。
簡単に説明すると、Scanner がエラー(例外処理)となった際にScannerをそのままループさせるとエラーとなったデータが引き継がられてしまいプログラムが停止してしまいます。
この問題の解決策として今回は『.nextLine();』を使用しました。

『.nextLine();』について、もっと詳しく知りたいと思った方は、下記サイトをご確認ください。
深いところまで解説されていましたので参考になるかと思います。
https://qiita.com/wing-x/items/187e988125a3bd7b2b32

・その他クラスについて

その他クラスは、Level_1と全く同じ内容となっています。Level _1の解説をご確認ください

4.まとめ

いかがでしたでしょうか。
例外処理は、1度プログラムを完成させておくと他のプログラムでも使用できるます。
また、意図しない箇所で止まる(エラーで停止する)事なく動き続けるプログラムを作成できるようになれ流という事は、ECサイトやアプリケーションを作成できるようになった(一歩近づいた)という事ではないでしょうか。(ワクワクしませんか?笑)

今回の問題が、少しでも読者の方の参考になれば幸いです。

練習問題Level_1の記事
練習問題Level_2の記事

コメント

タイトルとURLをコピーしました