こんにちは。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をもっと詳しく学びたい!という方には、下の書籍がおススメです!筆者も愛用しています。
