Javaプログラミング練習問題(継承 Part2)

Java

こんにちは。ECF Tech
ブログ担当 Michiharu.Tです。

Javaプログラミング向け練習問題、オブジェクト指向プログラミング編。今回はオブジェクト指向プログラミングの要ともいえる継承です。
今回はややプログラムにボリュームがあるものも用意しております。ぜひ、チャレンジしてみてください。

一般的なJavaの学習順序に沿ったテーマの一覧(※随時追加)は、こちらのリンクよりご確認頂けます。

Javaプログラミング

Javaのトピックスです。主に初心者向けにプログラミング学習ネタを提供していきます。

解説動画

2023/04/06 解説動画を掲載しました。

問題編

今回はメンバ変数、コンストラクタ、メソッドにアクセス修飾子を記述しています。特にことわりが無い場合は、下記のルールに基づきます。

  • メンバ変数はprivateアクセス
  • コンストラクタ、メソッドはpublicアクセス

Q001

問題

下の仕様に基づいて、各クラスを作成してください。
(仕様)
円を表すCircleクラスを作成します。次のメンバ変数、コンストラクタ、メソッドを作成し、Circle.javaとして保存します。

  • メンバ変数の作成
    • 円周率を表すPIをdouble型のクラス定数として定義します。初期値として3.14を代入します。(アクセス修飾子はpublicとします。)
    • 半径を表すhankeiをint型で宣言します。
  • コンストラクタの作成
    • 引数:
      • hankei:int型
    • 処理内容:引数で与えられた値を、同名のメンバ変数に代入します。
  • getAreaメソッドの作成
    • 概要:面積を計算し、結果を返します
    • 引数:なし
    • 戻り値:double型
    • 処理内容:メンバ変数hankeiとクラス定数PIを使って面積を計算し、戻り値として返します。計算方法は半径×半径×円周率とします。

円柱を表すCylinderクラスを、Circleクラスを継承して作成します。次のメンバ変数、コンストラクタ、メソッドを追加し、Cylinder.javaとして保存します。

  • メンバ変数の作成
    • 高さを表すheightをint型で宣言します。
  • コンストラクタの作成
    • 引数:
      • hankei:int型
      • height:int型
    • 処理内容:
      • 引数の値を同名のメンバ変数に設定します。
  • getVolumeメソッドの作成
    • 概要:円柱の体積を求めます。
    • 引数:なし
    • 戻り値:double型
    • 処理内容:
      • メンバ変数hankei, heightの値を使って円柱の体積を求め、戻り値として返します。計算方法は底面積×高さとします。

提供コード

下記のMain.javaを作成した他のソースファイルと同じフォルダ内に保存して動作確認し、実行結果が得られることを確認してください。

public class Main {
    public static void main(String[] args) {
        Circle circle = new Circle(10);
        System.out.println("半径10cmの円の面積は" + circle.getArea() + "平方cmです。");

        Cylinder cylinder = new Cylinder(8, 8);
        System.out.println("半径8cmの円の面積は"
                + cylinder.getArea() + "平方cmです。");
        System.out.println("半径8cm、高さ8cmの円柱の体積は" + cylinder.getVolume() + "立方cmです。");
    }    
}

実行結果

半径10cmの円の面積は314.0平方cmです。
半径8cmの円の面積は200.96平方cmです。
半径8cm、高さ8cmの円柱の体積は1607.68立方cmです。

Q002

問題

下の仕様に基づいて、各クラスを作成してください。
(仕様)
会員制ジムの会員を表すMemberクラスを作成します。次のメンバ変数、コンストラクタ、メソッドを作成し、Member.javaとして保存します。

  • メンバ変数の作成
    • 会員名称を表すnameをString型で宣言します。
    • 月額料金を表すmonthlyFeeをint型で宣言します。
  • コンストラクタの作成
    • 引数:name:String型
    • 処理内容:
      • メンバ変数nameに、引数nameを代入します。
      • メンバ変数monthlyFeeに、8000を代入します。
  • getNameメソッドの作成
    • 概要:アクセサメソッド
    • 引数:なし
    • 戻り値:String
    • 処理内容:メンバ変数nameの値を返します。
  • getMonthlyFeeメソッドの作成
    • 概要:アクセサメソッド
    • 引数:なし
    • 戻り値:int
    • 処理内容:メンバ変数monthlyFeeの値を返します。
  • isUsableメソッドの作成
    • 概要:指定の時間にジムの利用が可能かどうかを返します。
    • 引数:
      • hour:int型 利用する時間
    • 戻り値:boolean
    • 処理内容:
      • trueを返します。

会員制ジムの会員のうち、シニア会員を表すSeniorMemberクラスを作成します。Memberクラスを継承して作成します。次のコンストラクタ、メソッドを追加し、SeniorMember.javaとして保存します。

  • コンストラクタの作成
    • 引数:なし
    • 処理内容:
      • 引数の値を「シニア会員」とし、親クラスのコンストラクタを呼び出します。
  • getMonthlyFeeメソッドのオーバーライド
    • 処理内容:
      • メンバ変数monthlyFeeの70%の値を返します。monthlyFeeはアクセサメソッドを使って取得します。
        ※端数は切り捨てで構いません。

会員制ジムの会員のうち、時間制会員を表すLimitedMemberクラスを作成します。Memberクラスを継承して作成します。次のメンバ変数、コンストラクタ、メソッドを追加し、LimitedMember.javaとして保存します。

  • メンバ変数の作成
    • 利用可能開始時間を表すメンバ変数startTimeをint型で宣言します。
    • 利用可能終了時間を表すメンバ変数endTimeをint型で宣言します。

    メンバ変数startTimeとendTimeは、ジムの利用可能な時間帯を0~23の値(24時間表現)で保持します。また、下記のように日をまたがる時間帯になることがあります。

  • コンストラクタの作成
    • 引数:
      • name:String型
      • startTime:int型
      • endTime:int型
    • 処理内容:
      • 引数の値を同名のメンバ変数に設定します。
  • getMonthlyFeeメソッドのオーバーライド
    • 処理内容:
      • メンバ変数monthlyFeeの60%の値を返します。monthlyFeeはアクセサメソッドを使って取得します。
        ※端数は切り捨てで構いません。
  • isUsableメソッドのオーバーライド
    • 処理内容:
      • 引数hourの値がメンバ変数startTimeとendTimeが示す時間帯の範囲内ならtrueを返します。それ以外の場合はfalseを返します。
        ※利用可能開始時間と利用可能終了時間の示す時間帯が日またがりの場合も考慮します。
        ※startTime,endTimeそのものの時間も含みます。

提供コード

下記のMain.javaを作成した他のソースファイルと同じフォルダ内に保存して動作確認し、実行結果が得られることを確認してください。

public class Main {
    public static void main(String[] args) {
        Member sei = new Member("正会員");
        SeniorMember senior = new SeniorMember();
        LimitedMember daytime = new LimitedMember("デイタイム会員", 10, 20);
        LimitedMember night = new LimitedMember("ナイト会員", 20, 9);

        System.out.println("各会員料金");
        System.out.println( sei.getName() + ":" + sei.getMonthlyFee());
        System.out.println( senior.getName()+ ":" + senior.getMonthlyFee() );
        System.out.println( daytime.getName() + ":" + daytime.getMonthlyFee() );
        System.out.println( night.getName() + ":" + night.getMonthlyFee() );
        System.out.println();
        System.out.println("各会員の22時の利用");
        System.out.println( sei.getName() + ":" + sei.isUsable(22));
        System.out.println( senior.getName() + ":" + senior.isUsable(22));
        System.out.println( daytime.getName() + ":" + daytime.isUsable(22));
        System.out.println( night.getName() + ":" + night.isUsable(22));
    }    
}

実行結果

各会員料金
正会員:8000
シニア会員:5600
デイタイム会員:4800
ナイト会員:4800

各会員の22時の利用
正会員:true
シニア会員:true
デイタイム会員:false
ナイト会員:true

Q003

問題

下の仕様に基づいて、各クラスを作成してください。
(仕様)
冷房を表すCoolerクラスを作成します。次のメンバ変数、コンストラクタ、メソッドを作成し、Cooler.javaとして保存します。

  • メンバ変数の作成
    ※すべてpublicアクセスで定義します。
    • 現在温度を表すnowTempをint型で宣言します。
    • 設定温度を表すgoalTempをint型で宣言します。
  • コンストラクタの作成
    • 引数:
      nowTemp:int型
    • 処理内容: メンバ変数nowTempに、引数の値を設定します。
  • setGoalTempメソッドの作成
    • 概要:アクセサメソッドです
    • 引数:
      goalTemp:int型
    • 戻り値:なし
    • 処理内容: メンバ変数goalTempに、引数の値を設定します。
  • adjustメソッドの作成
    • 概要:室温を調節します
    • 引数:なし
    • 戻り値:なし
    • 処理内容:
      • 現在温度が設定温度より高ければ、現在温度を1度下げ「室温を1度下げました。」と表示する。
      • 現在温度が設定温度より低ければ、「適温です。」と表示する。

エアコンを表すAirConditionerクラスを、Coolerを継承して作成します。次のコンストラクタ、メソッドを作成し、AirConditioner.javaとして保存します。

  • コンストラクタの作成
    • 引数:
      nowTemp:int型
    • 処理内容: 親クラスのコンストラクタに、引数の値を渡して呼び出します。
  • adjustメソッドのオーバーライド
    • 処理内容:
      • 現在温度が設定温度より低ければ、現在温度を1度上げ「室温を1度上げました。」と表示する。
      • 現在温度が設定温度より高ければ、現在温度を1度下げ「室温を1度下げました。」と表示する。
      • 現在温度が設定温度と同じであれば、「適温です。」と表示します。

提供コード

下のMain.javaをコメントの指示(①~⑤)に基づいて追記します。
その後、作成した他のソースファイルと同じフォルダ内に保存して動作確認し、実行結果が得られることを確認してください。

(Main.java)

public class Main {
    public static void main(String[] args) {
        Cooler cooler = new Cooler(28);
        AirConditioner aircon = new AirConditioner(28);

        //冷房の設定温度を27度にする
        cooler.setGoalTemp(27);
        //冷房が温度調節をする
        cooler.adjust();
        //冷房が温度調節をする
        cooler.adjust();

        //エアコンの設定温度を27度にする
        ①
        //エアコンが温度調節をする
        ②
        //エアコンの設定温度を28度にする
        ③
        //エアコンが温度調節をする
        ④
        //エアコンが温度調節をする
        ⑤
    }    
}

実行結果

室温を1度下げました。
適温です。
室温を1度下げました。
室温を1度上げました。
適温です。

解答編

それでは、解答編です。

Q001

(Circle.java)

public class Circle {
    public static final double PI = 3.14;
    private int hankei; //半径

    public Circle(int hankei) {
        this.hankei = hankei;
    }

    public double getArea() {
        return hankei * hankei * PI;
    }
}

(Cylinder.java)

public class Cylinder extends Circle {
    private int height;

    public Cylinder(int hankei, int height) {
        super(hankei);
        this.height = height;
    }

    public double getVolume() {
        return super.getArea() * height;
    }
}

Q002

(Member.java)


public class Member {
    private String name;
    private int monthlyFee;

    Member(String name) {
        this.name = name;
        this.monthlyFee = 8000;
    }

    public String getName() {
        return this.name;
    }

    public int getMonthlyFee() {
        return monthlyFee;
    }

    public boolean isUsable(int hour) {
        return true;
    }

}

(SeniorMember.java)

public class SeniorMember extends Member {

    public SeniorMember() {
        super("シニア会員");
    }

    public int getMonthlyFee() {
        return (int)(super.getMonthlyFee() * 0.7);
    }
}

(LimitedMember.java)

public class LimitedMember extends Member {
    private int startTime;
    private int endTime;

    public LimitedMember(String name, int startTime, int endTime) {
        super(name);
        this.startTime = startTime;
        this.endTime = endTime;
    }

    public int getMonthlyFee() {
        return (int) (super.getMonthlyFee() * 0.6);
    }

    public boolean isUsable(int hour) {
        if (startTime <= endTime) {
            if (startTime <= hour && hour <= endTime) {
                return true;
            }
            return false;
        } else {
            if( (startTime <= hour && hour <= 23) || 
                    (0 <= hour && hour <= endTime)) {
                return true;
            }
            return false;
        }
    }
}

Q003

(Cooler.java)

public class Cooler {
    public int nowTemp;
    public int goalTemp;

    public Cooler(int nowTemp) {
        this.nowTemp = nowTemp;
    }

    public void setGoalTemp(int goalTemp) {
        this.goalTemp = goalTemp;
    }

    public void adjust() {
        if (nowTemp > goalTemp) {
            nowTemp--;
            System.out.println("室温を1度下げました。");
        } else {
            System.out.println("適温です");
        }
    }
}

(AirConditioner.java)

public class AirConditioner extends Cooler{
    public AirConditioner(int nowTemp) {
        super(nowTemp);
    }

    public void adjust() {
        if (nowTemp < goalTemp) {
            nowTemp++;
            System.out.println("室温を1度上げました。");
        } else {
            super.adjust();
        }
    }
}

(Main.java)

public class Main {
    public static void main(String[] args) {
        Cooler cooler = new Cooler(28);
        AirConditioner aircon = new AirConditioner(28);

        //冷房の設定温度を27度にする
        cooler.setGoalTemp(27);
        //冷房が温度調節をする
        cooler.adjust();
        //冷房が温度調節をする
        cooler.adjust();

        //エアコンの設定温度を27度にする
        aircon.setGoalTemp(27);
        //エアコンが温度調節をする
        aircon.adjust();
        //エアコンの設定温度を28度にする
        aircon.setGoalTemp(28);
        //エアコンが温度調節をする
        aircon.adjust();
        aircon.adjust();
    }    
}

おわりに

本日は以上となります。最後までご覧くださりありがとうございます。継承の事例体験をとおして、継承の楽しさや便利さが少しでもお伝えできれば幸いです。ひきつづき、問題の提供をしていければと思っています。今後もよろしくお願いいたします。


合同会社イー・シー・エフでは、子ども向けプログラミングなどの教育講座を実施しています。プログラミング教室の案内や教育教材の情報、また関連するご相談・問い合わせにつきましては下記よりご確認ください。

ECFエデュケーション
タイトルとURLをコピーしました