問題2-6
車を表すCarクラスを作成してください。
Carクラスを使用するConstructorOverloadPracticeクラスのmainメソッドはすでに完成しています。
(変更は禁止です)
【Carクラス】
車幅を表すtypeインスタンスフィールド(String型)と、ナンバーを表すnumberインスタンスフィールド(int型)と、ガソリンを表すgasolineインスタンスフィールド(double型)の3つがあります。
コンストラクタをオーバーロードして2つ定義します。
1つ目は、第一引数に車種、第二引数にナンバー、第三引数にガソリンを受け取り、引数の値をインスタンスフィールドに受け渡します。
2つ目は、第一引数に車種、第二引数にナンバーを受け取り、引数の値をインスタンスフィールドに受け渡します。
ガソリンの量は初期値として5.0を設定します。走行を表現するrunインスタンスメソッドを定義します。
戻り値はなし、引数には走行する分のガソリン量(double型)を設定します。
もし残ガソリン量が、走行ガソリン量に満たない場合は、「ナンバー○○の△△はガソリン不足のため走行できません」と出力します。車の情報を表示するshowInfoインスタンスメソッドを定義します。
引数と戻り値はなしで、実装は下記実行結果を参考にしてください。
【実行結果】
ナンバー1234のトントはガソリン7.0リットル分走行しました ナンバー6789のファットはガソリン不足のため走行できません 車種:トント ナンバー:1234 ガソリン:3.0リットル 車種:ファット ナンバー:6789 ガソリン:5.0リットル
【ConstructorOverloadPractice.java】
public class ConstructorOverloadPractice { public static void main(String[] args) { // 1台目の車インスタンス生成 Car car1 = new Car("トント", 1234, 10.0); // 2台目の車インスタンス生成 Car car2 = new Car("ファット", 6789); // 2台の車を走行させる car1.run(7.0); car2.run(7.0); // 2台の車の情報を出力 car1.showInfo(); car2.showInfo(); } } // ここにCarクラスを作成してください
解答例
【ConstructorOverloadPractice.java】
public class ConstructorOverloadPractice { public static void main(String[] args) { // 1台目の車インスタンス生成 Car car1 = new Car("トント", 1234, 10.0); // 2台目の車インスタンス生成 Car car2 = new Car("ファット", 6789); // 2台の車を走行させる car1.run(7.0); car2.run(7.0); // 2台の車の情報を出力 car1.showInfo(); car2.showInfo(); } } // 車クラス class Car { // 車種 private String type; // ナンバー private int number; // ガソリン private double gasoline; // コンストラクタ public Car(String type, int number, double gasoline) { this.type = type; this.number = number; this.gasoline = gasoline; } // コンストラクタ public Car(String type, int number) { this(type, number, 5.0); } // 情報表示メソッド public void showInfo() { System.out.println("車種:" + type + " ナンバー:" + number + " ガソリン:" + gasoline + "リットル"); } // 走行メソッド public void run(double need) { // ガソリンが足りている場合 if(gasoline >= need) { System.out.println("ナンバー" + number + "の" + type + "はガソリン" + need + "リットル分走行しました"); // 走行分だけガソリンを減らす gasoline -= need; } // ガソリンが不足している場合 else { System.out.println("ナンバー" + number + "の" + type + "はガソリン不足のため走行できません"); } } }
解説
Javaには「オーバーロード」という仕組みがあります。
同じクラスに、同じ名前のメソッドを複数定義できることを指します。
(ただし、引数の数と引数の型の組み合わせは異なっている必要があります)
コンストラクタも「特殊なメソッド」ですから、オーバーロードすることが可能です。
今回作成する車クラスは、車種とナンバーとガソリンの3つのインスタンスフィールドを持ちます。
コンストラクタの主な目的は、インスタンスフィールドの初期値の設定ですす。
よって、引数3つのコンストラクタは定義したいところです。
3つのインスタンスフィールドのうち、車種とナンバーは一度初期値を設定すると値が変動しない特に重要なものです。
ですので、引数2つのコンストラクタも定義しました。
これが「オーバーロード」です。
その場合、仕様としてガソリンの初期値をデフォルト値「5.0」に設定しました。
2つのコンストラクタを次のように記述した人もいるでしょう。
// コンストラクタ public Car(String type, int number, double gasoline) { this.type = type; this.number = number; this.gasoline = gasoline; } // コンストラクタ public Car(String type, int number) { this.type = type; this.number = number; this.gasoline = 5.0 }
もちろん、間違いではないです。
しかし、Javaでは解答例のように、補助的なコンストラクタ(引数2つバージョン)は、内部的にメインとなるコンストラクタ(引数3つバージョン)を呼び出してうまく連結させるのがうまいやり方です。
最低限、コンストラクタの1行目では、1度だけthisキーワードを用いてオーバーロードしたコンストラクタを呼び出せることは絶対に知っておいてください。
この時、thisキーワードの後ろに丸括弧をつけてメソッド呼び出しのような形にするのがポイントです。
(コンストラクタの1行目には、superキーワードを用いてスーパークラスのコンストラクタを呼び出すことも可能です。)
小さなポイントとしては、走行runメソッドで車を走行させた場合は、きちんと走行ガソリン分だけ残ガソリンを減らさないといけません。
オブジェクトの状態(ステートと言います)を場合に応じてきちんと変化させることは非常に大切なことです。
参考図書
LINE公式アカウント
仕事が辛くてたまらない人生が、仕事が楽しくてたまらない人生に変わります。
【登録いただいた人全員に、無料キャリア相談プレゼント中!】