Java.オブジェクト指向練習問題Level_1の続きの練習問題Level_2です。
Level_2から挑戦しても大丈夫かと思いますが、難しいと感じた方は練習問題Level_1の記事を先にご確認ください。
初学者向けに作られた(受講した講座に出てきた)問題を記載しています。
読者の参考になれば幸いです。
(環境:Mac・Eclipse_2020-12を使用しています。)
Level_1からLevel_3と段階的に難易度を分けて問題を記載しています。
Level_2については、『抽象クラス』『カプセル化』『ポリモーフィズム』を学べる内容になっているかと思います。
抽象クラスの使い方のルールさえ分かれば、Level_1の内容を利用してコードを書く事ができるかと思います。
あまり身構えずに、ぜひチャレンジしてください!
注意:問題の回答は、私なりの回答となっています。正解でない場合もあると思いますのでご了承ください。。
1.オブジェクト指向・問題Level_2(メニュー注文表)
下記の仕様書に従って、プログラムを作成しなさい。
※仕様書の中で不足箇所があると判断した場合は、変更・追加して良い事とする。
(Level_1で作成したプログラムを参考にして)抽象クラスを利用した内容のプログラムを作成しなさい。
クラス一覧
| 修飾子 | クラス名 | 説明 |
| public sbstract | AbstractSize | サイズ選択(抽象クラス) |
| public | Hamberger | ハンバーガーのサイズ選択(AbstractSizeのサブクラス) |
| public | FrenchFries | ポテトのサイズ選択(AbstractSizeのサブクラス) |
| public | Drink | ドリンクのサイズ選択(AbstractSizeのサブクラス) |
| public | Calc | 計算 |
| public | OrderMain | 金額の表示 |
○AbstractSizeクラス
【フィールド】(getter/setterを作成)
| 修飾子 | 型 | 名前 | 説明 |
| private | String | name | 商品名 |
【コンストラクタ】
| 修飾子 | 引数 | 説明 |
| protected | String name | フィールドに値を代入する |
【メソッド】
| 修飾子 | 戻り値の型 | 名前 | 引数 | 説明 |
| public abstract | int | selectSize | なし | 標準入力された値から値段を判別して返す抽象メソッド |
○Hamberger、FrenchFries、Drinkクラス
【フィールド】
| 型 | 名前 | 説明 |
| String | name | 商品名 |
【コンストラクタ】
| 引数 | 説明 |
| String | フィールドに値を代入する |
【メソッド】
| 戻り値の型 | 名前 | 引数 | 説明 |
| Int | selectSize | なし | ・フイールドの値(商品名)を表示する ・Mainクラスにて、標準入力で1〜3が入力された場合の値を設定し、値から値段を判別して返す(switch文を利用) |
○Calcクラス
【メソッド】
| 戻り値の型 | 名前 | 引数 | 説明 |
| Int | total | int ham int ff int dri | 注文商品のサイズの金額を引数として受け取り、全て足して合計を返す。 |
○OrderMainクラス
【mainメソッド】
1、各クラスのインスタンスを生成する(コンストラクタの引数に適当な値を代入する)
2、3つのインスタンスの selectSizeメソッドを呼び出す
3、各フィールドの値と各メソッドの戻り値(商品名と選択肢たサイズの値段)を表示
4、Calc のインスタンスの totalメソッドを呼び出す
5、total メソッドの戻り値を表示する
【表示例】
メニューのサイズを選択してください。
チーズバーガー
1:シングル、2:ダブル、3:トリプル
1
ポテト
1:S、2:M、3:L
1
ジンジャーエール
1:S、2:M、3:L
1
[選んだメニュー]
チーズバーガー:240円
ポテト:180円
コーラ:110円
お会計は 530円です。
2.回答例
・AbstractSizeクラス
public abstract class AbstractSize {
private String name ; //名前の設定
//コンストラクタの設定
protected AbstractSize(String name) {
this.setName(name) ;
}
//名前と金額を表示させるメソッド
public void namePrint() {
System.out.println(name + ":" + selectSize());
}
//抽象メソッド
public abstract int selectSize();
//getter&setter の作成
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
・Hamburgerクラス
public class Hamburger2 extends AbstractSize {
String name ; //名前の設定
int num ; //金額の設定
//コンストラクタの設定
protected Hamburger2(String name,int num) {
super(name); //スーパークラスのメンバ変数の呼び出し
this.num = num ;
}
public int selectSize() {
int price = 0; //金額の設定
//1or2or3が代入された時の分岐
switch (num) {
case 1:
price = 240;
break;
case 2:
price = 360;
break;
default:
price = 480;
}
return price;
}
}
・FrenchFriesクラス
public class FrenchFries2 extends AbstractSize {
String name ; //名前の設定
int num ; //金額の設定
//コンストラクタの設定
protected FrenchFries2(String name,int num) {
super(name); //スーパークラスのメンバ変数の呼び出し
this.num = num ;
}
public int selectSize() {
int price = 0; //金額の設定
//1or2or3が代入された時の分岐
switch (num) {
case 1:
price = 180;
break;
case 2:
price = 240;
break;
default:
price = 280;
}
return price;
}
}
・Drinkクラス
public class Drink2 extends AbstractSize {
String name ; //名前の設定
int num ; //金額の設定
//コンストラクタの設定
protected Drink2(String name,int num) {
super(name); //スーパークラスのメンバ変数の呼び出し
this.num = num ;
}
public int selectSize() {
int price = 0; //金額の設定
//1or2or3が代入された時の分岐
switch (num) {
case 1:
price = 110;
break;
case 2:
price = 170;
break;
default:
price = 210;
}
return price;
}
}
・Calcクラス
public class Calc2 {
public int total(int ham, int ff, int dri) {
int sum = 0;
sum = ham + ff + dri;
return sum;
}
}
・OrderMainクラス
public class OrderMain2 {
public static void main(String[] args) {
System.out.println("メニューのサイズを選んでください");
String hamburger = "チーズバーガー";
System.out.println(hamburger);
System.out.println("1:シングル、2:ダブル、3:トリプル");
Scanner scan1 = new Scanner(System.in);
int hbselect = scan1.nextInt();
Hamburger2 hb = new Hamburger2(hamburger, hbselect);
String frenchfries = "ポテト";
System.out.println(frenchfries);
System.out.println("1:S、2:M、3:L");
Scanner scan2 = new Scanner(System.in);
int ffselect = scan2.nextInt();
FrenchFries2 frenh = new FrenchFries2(frenchfries, ffselect);
String drink = "コーラ";
System.out.println(drink);
System.out.println("1:S、2:M、3:L");
Scanner scan3 = new Scanner(System.in);
int dkselect = scan3.nextInt();
Drink2 dk = new Drink2(drink, dkselect);
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();
}
}
3.解説
・AbstractSizeクラスについて
仕様書の中にメソッドが1つ不足していると判断して、下記のメソッドを追加しました。
//名前と金額を表示させるメソッド
public void namePrint() {
System.out.println(name + ":" + selectSize());
}
そして後述もしますが、Level_1のHamberger、FrenchFries、Drinkクラスに記載していました『System.out.println(name + “:” ); 』の部分を削除しています。
この記載の仕方が、個人的に納得する回答で無駄なコードも減らせると思った為です(汗
また抽象メソッドのルールに『中身が無いメソッドが少なくとも1つ含まれている』とあるので、私は『public abstract int selectSize(); 』のコードに中身の無いメソッドを作りました。
・Hamberger、FrenchFries、Drinkクラスについて
ほとんどLevel_1と同じ内容ですが、2点変更を加えました。
1つ目は、コンストラクタの定義の『name』は、AbstractSizeのスーパークラスメンバ変数として『super(name); 』と記載しています。
2つ目は、前述した『System.out.println(name + “:” ); 』の部分を削除しています。
AbstractSizeクラスにて名前を表記するように設定した事により記載が不要になった為です。
・Clacクラスについて
このクラスは、Level_1と全く同じ内容となっています。前回より変更はありません。
・OrderMainクラスについて
まずはLevel_1と同じ処理、『商品名の設定』と『コンストラクタにサイズを指定した数字(標準入力した数字)も代入』しています。
そして、各クラスの金額を表示する『System.out.println(ham + “円”); 』を削除した代わりに『○○.namePrintln(); 』を記述しました。
※この記載をすることで仕様書の指示通りの『商品名:金額』が表示されます。
また、文末に記載している scan.close() メソッドについては、Level_1にて解説していますのでご確認ください。
4.まとめ
いかがでしたでしょうか。
私も抽象クラスについて、完璧に理解して使用できていないと思いますが、ルールが分ればコードの記述が減らせるメリットがあると感じています。
『カプセル化』『ポリモーフィズム』と合わせて『抽象クラス』について、少しでも読者の方の参考になれば幸いです。
次の問題では、例外処理を実装する問題を用意しています。
Java.オブジェクト指向の練習問題Level_3(メニュー注文表)

コメント