こんにちは。ECF Tech
ブログ担当 Michiharu.Tです。
Javaプログラミング向け練習問題、オブジェクト指向プログラミング編。今回は抽象化・多態性がテーマです。多態性そのものを問題にする内容ではありませんが、動作確認のMainクラスでは、多態性を活かしたプログラムになっています。ぜひ普段の学習にお役立てください。
一般的なJavaの学習順序に沿ったテーマの一覧(※随時追加)は、こちらのリンクよりご確認頂けます。
Javaのトピックスです。主に初心者向けにプログラミング学習ネタを提供していきます。
解説動画
2023/05/27 解説動画を掲載しました。
問題編
アクセス修飾子について:
各問題のメンバ変数、コンストラクタ、メソッド定義において特にことわりが無い場合、すべてpublicを指定してください。
Q001
問題
下の仕様に基づいて、各クラスを作成してください。
(仕様)
ゲームに登場するアイテムを表すItemクラスを抽象クラスとして作成します。次のメンバ変数、コンストラクタ、メソッドを作成し、Item.javaとして保存します。
- メンバ変数の作成
- 名前を表すnameをString型で宣言します。
- 修正値を表すvalueをint型で宣言します。
- コンストラクタの作成
- 引数:
- name:String型
- value:int型
- 処理内容:引数で与えられた値を、同名のメンバ変数に代入します。
- 引数:
- useメソッドの作成(抽象メソッド)
- 概要:アイテムを使った場合の処理を記述します。
- 引数:なし
- 戻り値:なし
武器を表すBukiクラスを、Itemクラスを継承して作成します。次のメンバ変数、コンストラクタ、メソッドを追加し、Buki.javaとして保存します。
- コンストラクタの作成
- 引数:
- name:String型
- value:int型
- 処理内容:
- 渡された2つの引数を用いて、親クラスのコンストラクタを呼び出します。
- 引数:
- useメソッドの実装
useメソッドをオーバーライドし、次のように処理をします。- 処理内容:
- 「xxxxでこうげき!!」と表示します。(xxxxはメンバ変数nameの値が入ります)
- 「敵にyyのダメージ!」と表示します。(yyはメンバ変数valueの値が入ります)
- 処理内容:
防具を表すArmorクラスを、Itemクラスを継承して作成します。次のメンバ変数、コンストラクタ、メソッドを追加し、Armor.javaとして保存します。
- コンストラクタの作成
- 引数:
- name:String型
- value:int型
- 処理内容:
- 渡された2つの引数を用いて、親クラスのコンストラクタを呼び出します。
- 引数:
- useメソッドの実装
useメソッドをオーバーライドし、次のように処理をします。- 処理内容:
- 「xxxxを身に着けた」と表示します。(xxxxはメンバ変数nameの値が入ります)
- 「守備力がyy上がった」と表示します。(yyはメンバ変数valueの値が入ります)
- 処理内容:
提供コード
下記のMain.javaを作成した他のソースファイルと同じフォルダ内に保存して動作確認し、実行結果が得られることを確認してください。
public class Main { public static void main(String[] args) { Item[] items = { new Buki("鉄の剣",20), new Armor("皮の服",10) }; for (Item item : items) { item.use(); } } }
実行結果
鉄の剣でこうげき!! 敵に20のダメージ! 皮の服を身に着けた 守備力が10上がった
Q002
問題
下の仕様に基づいて、各クラス・インタフェースを作成してください。
(仕様)
「転送可能」という特徴を表すTransferableインタフェースを作成します。次の抽象メソッドを作成し、Transferable.javaとして保存します。
- transferメソッドの作成(抽象メソッド)
- 概要:データの転送処理を行ないます
- 引数:なし
- 戻り値:なし
スイッチ(通信機器)を表すSwitchクラスを、Transferableインタフェースを実装して作成します。次のメンバ変数、コンストラクタ、メソッドを追加し、Switch.javaとして保存します。
- transferメソッドの実装
- 処理内容:
- 「MACアドレスを使ってデータを転送します」と表示します。
- 処理内容:
ルータ(通信機器)を表すRouterクラスを、Transferableインタフェースを実装して作成します。次のメンバ変数、コンストラクタ、メソッドを追加し、Router.javaとして保存します。
- transferメソッドの実装
- 処理内容:
- 「IPアドレスを使ってデータを転送します」と表示します。
- 処理内容:
提供コード
下記のMain.javaを作成した他のソースファイルと同じフォルダ内に保存して動作確認し、実行結果が得られることを確認してください。
public class Main { public static void main(String[] args) { Transferable[] parts = { new Switch(), new Router() }; for (Transferable work : parts) { work.transfer(); } } }
実行結果
MACアドレスを使ってデータを転送します IPアドレスを使ってデータを転送します
Q003
問題
下の仕様に基づいて、各クラス・インタフェースを作成してください。
(仕様)
お店のクーポン券を表すCouponインタフェースを作成します。次の抽象メソッドを作成し、Coupon.javaとして保存します。
- discountメソッドの作成(抽象メソッド)
- 概要:引数で受け取った金額から一定の値下げを行ない、値下げの値を返します。
- 引数:amount:int型
- 戻り値:int型
割引クーポンを表すPercentageCouponクラスを、Couponインタフェースを実装して作成します。次のメンバ変数、コンストラクタ、メソッドを追加し、PercentageCoupon.javaとして保存します。
- メンバ変数の作成
- 割引率を表すrateをdouble型で定義します。
- コンストラクタの作成
- 引数:
- rate:double型
- 処理内容:引数で与えられた値を、同名のメンバ変数に代入します。
- 引数:
- discountメソッドの実装
- 処理内容:
- メンバ変数rateの値に基づいて割引額を求め(小数点以下は切り捨て)、引数amountから割引額を引いた値を返します。
- 処理内容:
定額クーポンを表すFixedCouponクラスを、Couponインタフェースを実装して作成します。次のメンバ変数、コンストラクタ、メソッドを追加し、FixedCoupon.javaとして保存します。
- メンバ変数の作成
- 割引額を表すdiscountAmountをint型で定義します。
- コンストラクタの作成
- 引数:
- discountAmount:int型
- 処理内容:引数で与えられた値を、同名のメンバ変数に代入します。
- 引数:
- discountメソッドの実装
- 処理内容:
- 引数amountの値からメンバ変数discountAmountの値を引き算した結果を返します。
- 処理内容:
レジを表すCasherクラスを作成します。次のクラスメソッドを作成し、Casher.javaとして保存します。
- paymentメソッド(クラスメソッド)の作成
- 概要:金額とクーポンの情報から、合計額を計算します
- 引数:
- amount:int型
- coupon:Coupon型
- 戻り値:int型
- 処理内容:amountの値を引数として、couponのdiscountメソッドを呼び出します。discountメソッドの戻り値をそのまま返します。
提供コード
下記のMain.javaの①~④の記述に基づき、プログラムを追記します。他のソースファイルと同じフォルダ内に保存して動作確認し、実行結果が得られることを確認してください。
public class Main { public static void main(String[] args) { PercentageCoupon coupon1 = new PercentageCoupon(0.3); FixedCoupon coupon2 = new FixedCoupon(1000); System.out.println(Casher.payment(5000, coupon1)); System.out.println(Casher.payment(5000, coupon2)); //①変数coupon3を宣言します。5割引のクーポンを生成し代入します。 //②変数coupon4を宣言します。1500円引のクーポンを生成し代入します。 //③Casherのpaymentメソッドを呼び出し、5000円に対してcoupon3を適用した結果を表示します。 //④Casherのpaymentメソッドを呼び出し、5000円に対してcoupon4を適用した結果を表示します。 } }
実行結果
3500 4000 2500 3500
Q004
問題
下の仕様に基づいて、各クラスを作成してください。
(仕様)
クイズを表すQuizクラスを作成します。次のメンバ変数、コンストラクタ、メソッドを追加し、Quiz.javaとして保存します。
- メンバ変数の作成
- 問題文を表すmainをString型で定義します。※privateアクセスとします。
- コンストラクタの作成
- 引数:
- main:String型
- 処理内容:引数で与えられた値を、同名のメンバ変数に代入します。
- 引数:
- displayHeaderメソッドの作成
- 概要:問題の冒頭文を表示します。
- 引数:なし
- 戻り値:なし
- 処理内容:「次の問いに答えなさい」と表示します。(※「」も表示内容です)
- displayMainメソッドの作成
- 概要:問題の本文を表示します。
- 引数:なし
- 戻り値:なし
- 処理内容:メンバ変数mainの内容を表示します。
選択肢つきクイズを表すMultipleChoiceQuizクラスを、Quizクラスを継承して作成します。次のメンバ変数、コンストラクタ、メソッドを追加しMultipleChoiceQuiz.javaとして保存します。
- メンバ変数の作成
- 選択肢を表すanswersをString型の配列で定義します。
- コンストラクタの作成
- 引数:
- main:String型
- answers:String型配列
- 処理内容:
- 引数mainの値を用いて、親クラスのコンストラクタを呼び出します。
- 引数answersは、メンバ変数answersにそのまま代入します。
- 引数:
- displayHeaderメソッドの作成
- 概要:問題の冒頭文を表示します。
- 引数:なし
- 戻り値:なし
- 処理内容:「次の問いについて、正しいものを4つの中から選びなさい」と表示します。(※「」も表示内容です)
- displayMainメソッドの作成
- 概要:問題の本文を表示します。
- 引数:なし
- 戻り値:なし
- 処理内容:
- メンバ変数mainの内容を表示します。
- メンバ変数answersの各要素を、「x:yyyyyy」の形式で表示します。
xは1から始まる連続番号
yyyyyyはanswersの各要素です。
穴埋めクイズを表すBlankQuizクラスを、Quizクラスを継承して作成します。次のメンバ変数、コンストラクタ、メソッドを追加し、BlankQuiz.javaとして保存します。
- メンバ変数の作成
- 空欄の数を表すblankCountをint型で定義します。
- コンストラクタの作成
- 引数:
- main:String型
- blankCount:int型
- 処理内容:
- 引数mainの値を用いて、親クラスのコンストラクタを呼び出します。
- 引数blankCountは、メンバ変数blankCountにそのまま代入します。
- 引数:
- displayHeaderメソッドの作成
- 概要:問題の冒頭文を表示します。
- 引数:なし
- 戻り値:なし
- 処理内容:「次の文の空欄を埋めなさい」と表示します。(※「」も表示内容です)
- displayMainメソッドの作成
- 概要:問題の本文を表示します。
- 引数:なし
- 戻り値:なし
- 処理内容:
- メンバ変数mainの内容を表示します。
- メンバ変数blankCountの数だけ、「x. ______________」と表示します。
xは1から始まる連続番号
クイズを表示するためのQuizViewerクラスを作成します。次のクラス変数とクラスメソッドを作成し、QuizViewer.javaとして保存します。
- クラス変数の作成
- 問題番号を表すcountをint型で定義します。
- showQuizメソッドの作成(クラスメソッド)
- 概要:問題を表示します。
- 引数:quiz:Quiz型
- 戻り値:なし
- 処理内容:
- メンバ変数countを1加算します。
- 「<第x問>」と表示します。(xはメンバ変数countの値が入ります。)
- 引数quizのdisplayHeaderメソッドを呼び出します。
- 引数quizのdisplayMainメソッドを呼び出します。
- 改行します。
提供コード
下記のMain.javaを作成した他のソースファイルと同じフォルダ内に保存して動作確認し、実行結果が得られることを確認してください。
public class Main { public static void main(String[] args) { Quiz q1 = new Quiz("最も面積の広い都道府県はどこですか?"); String[] answers = {"青りんご","さくらんぼ","みかん","ぶどう"}; Quiz q2 = new MultipleChoiceQuiz("赤色の果物はどれですか", answers); Quiz q3 = new BlankQuiz("( )は( )年に鎌倉幕府を設立した。", 2); QuizViewer.showQuiz(q1); QuizViewer.showQuiz(q2); QuizViewer.showQuiz(q3); } }
実行結果
<第1問> 「次の問いに答えなさい」 最も面積の広い都道府県はどこですか? <第2問> 「次の問いについて、正しいものを4つの中から選びなさい」 赤色の果物はどれですか 1:青りんご 2:さくらんぼ 3:みかん 4:ぶどう <第3問> 「次の文の空欄を埋めなさい」 ( )は( )年に鎌倉幕府を設立した。 1. ______________ 2. ______________
解答編
それでは、解答編です。
Q001
(Item.java)
public abstract class Item { String name; int value; Item(String name, int value) { this.name = name; this.value = value; } public abstract void use(); }
(Buki.java)
public class Buki extends Item{ Buki(String name, int value) { super(name, value); } public void use() { System.out.println(this.name + "でこうげき!!"); System.out.println("敵に" + this.value + "のダメージ!"); } }
(Armor.java)
public class Armor extends Item { Armor( String name, int value) { super(name,value); } public void use() { System.out.println(this.name + "を身に着けた"); System.out.println("守備力が" + this.value + "上がった"); } }
Q002
(Transferable.java)
public interface Transferable { public void transfer(); }
(Switch.java)
public class Switch implements Transferable { public void transfer() { System.out.println("MACアドレスを使ってデータを転送します"); } }
(Router.java)
public class Router implements Transferable{ public void transfer() { System.out.println("IPアドレスを使ってデータを転送します"); } }
Q003
(Coupon.java)
public interface Coupon { public int discount(int amount); }
(PercentageCoupon.java)
public class PercentageCoupon implements Coupon { double rate; public PercentageCoupon(double rate) { this.rate = rate; } public int discount(int amount) { return (int)(amount * rate); } }
(FixedCoupon.java)
public class FixedCoupon implements Coupon{ int discountAmount; public FixedCoupon(int discountAmount) { this.discountAmount = discountAmount; } public int discount(int amount) { return amount - discountAmount; } }
(Casher.java)
public class Casher { public static int payment(int amount, Coupon coupon) { int ret = coupon.discount(amount); return ret; } }
(Main.java)
public class Main { public static void main(String[] args) { PercentageCoupon coupon1 = new PercentageCoupon(0.3); FixedCoupon coupon2 = new FixedCoupon(1000); System.out.println(Casher.payment(5000, coupon1)); System.out.println(Casher.payment(5000, coupon2)); //①変数coupon3を宣言します。5割引のクーポンを生成し代入します。 PercentageCoupon coupon3 = new PercentageCoupon(0.5); //②変数coupon4を宣言します。1500円引のクーポンを生成し代入します。 FixedCoupon coupon4 = new FixedCoupon(1500); //③Casherのpaymentメソッドを呼び出し、5000円に対してcoupon3を適用した結果を表示します。 System.out.println(Casher.payment(5000,coupon3)); //④Casherのpaymentメソッドを呼び出し、5000円に対してcoupon4を適用した結果を表示します。 System.out.println(Casher.payment(5000,coupon4)); } }
Q004
(Quiz.java)
public class Quiz { private String main; public Quiz(String main) { this.main = main; } public void displayHeader() { System.out.println("「次の問いに答えなさい」"); } public void displayMain() { System.out.println(main); } }
(MultipleChoiceQuiz.java)
public class MultipleChoiceQuiz extends Quiz{ String[] answers; public MultipleChoiceQuiz(String main, String[] answers) { super(main); this.answers = answers; } public void displayHeader() { System.out.println("「次の問いについて、正しいものを4つの中から選びなさい」"); } public void displayMain() { super.displayMain(); for (int i = 0; i < answers.length; i++) { System.out.println( (i+1) + ":" + answers[i] ); } } }
(BlankQuiz.java)
public class BlankQuiz extends Quiz { int blankCount; public BlankQuiz(String main, int blankCount) { super(main); this.blankCount = blankCount; } public void displayHeader() { System.out.println("「次の文の空欄を埋めなさい」"); } public void displayMain() { super.displayMain(); for (int i = 0; i < blankCount; i++) { System.out.println( (i+1) + ". ______________" ); } } }
(QuizViewer.java)
public class QuizViewer { public static int count; public static void showQuiz(Quiz quiz) { count++; System.out.println("<第" + count + "問>"); quiz.displayHeader(); quiz.displayMain(); System.out.println(); } }
おわりに
本日は以上となります。最後までご覧くださりありがとうございます。初学者の方が多態性の動作イメージをつかむ一助になれば幸いです。ひきつづき、問題の提供をしていければと思っています。今後もよろしくお願いいたします。
[PR]
Javaをもっと詳しく学びたい!という方には、下の書籍がおススメです!筆者も愛用しています。