スッキリわかるJava入門 第9章 さまざまなクラス機構(練習問題)
第9章 さまざまなクラス機構(練習問題)
練習9
public class Cleric { // コンストラクタ public Cleric(String name, int hp, int mp) { this.name = name; this.hp = hp; this.mp = mp; } public Cleric(String name, int hp) { this(name, hp, MAX_MP); } public Cleric(String name) { this(name, MAX_HP, MAX_MP); } // 名前 String name; // HP int hp = 50; // 最大HP static final int MAX_HP = 50; // staticを追加 // MP int mp = 10; // 最大MP static final int MAX_MP = 10; // staticを追加 // 魔法_セルフエイド public void selfAid() { System.out.println(name + "は魔法「セルフエイド」を唱えた!"); // MPを5消費 this.mp -= 5; // HPを最大HPまで回復 this.hp = this.MAX_HP; System.out.println("最大HPまで回復した."); } // 祈る public int pray(int sec) { System.out.println(name + "は、" + sec + "秒祈った!"); // ランダムで0~2ポイント補正 int correction = new java.util.Random().nextInt(3); System.out.println("** 補正ポイント:" + correction); // MP回復量(仮) int tempAidPoint = sec + correction; // 最大MPより回復しないよう制御 //(MP回復量(仮)またはMP減少値の最小値を採用) int aidPoint = Math.min(tempAidPoint, this.MAX_MP - this.mp); System.out.println("** 回復前のMP:" + this.mp); // MP回復 this.mp += aidPoint; System.out.println("MPが" + aidPoint + "ポイント回復した."); System.out.println("** 回復後のMP:" + this.mp); return aidPoint; } }
public class Main { public static void main (String[] args) { // コンストラクタ1 Cleric clericShuto = new Cleric("シュウトウ"); System.out.println("名前:" + clericShuto.name); System.out.println("HP:" + clericShuto.hp); System.out.println("MP:" + clericShuto.mp); // コンストラクタ2 Cleric clericKondoh = new Cleric("コンドウ", 30); System.out.println("名前:" + clericKondoh.name); System.out.println("HP:" + clericKondoh.hp); System.out.println("MP:" + clericKondoh.mp); // コンストラクタ3 Cleric clericGita = new Cleric("ギータ", 40, 9); System.out.println("名前:" + clericGita.name); System.out.println("HP:" + clericGita.hp); System.out.println("MP:" + clericGita.mp); // コンストラクタ3 Cleric clericKuri = new Cleric("クリハラ", 100, 100); System.out.println("名前:" + clericKuri.name); System.out.println("HP:" + clericKuri.hp); System.out.println("MP:" + clericKuri.mp); } }
実行結果
C:\work\ex91>java Main 名前:シュウトウ HP:50 MP:10 名前:コンドウ HP:30 MP:10 名前:ギータ HP:40 MP:9 名前:クリハラ HP:100 MP:100
改善①:コンストラクタの重複コードが最小限となるように修正
修正前
// コンストラクタ public Cleric(String name) { this.name = name; } public Cleric(String name, int hp) { this(name); // コンストラクタ1を呼出し this.hp = hp; } public Cleric(String name, int hp, int mp) { this(name, hp); // コンストラクタ2を呼出し this.mp = mp; }
修正後
// コンストラクタ public Cleric(String name, int hp, int mp) { this.name = name; this.hp = hp; this.mp = mp; } public Cleric(String name, int hp) { this(name, hp, this.MAX_MP); } public Cleric(String name) { this(name, this.MAX_HP, this.MAX_MP); }
改善②:コンパイルエラーを修正(修正後の「 this.MAX_HP」「this.MAX_MP」)
- コンストラクタはインスタンス生成前なので、thisを用いて「自分自身のインスタンスのメンバ」は利用できない。thisは「自分自身のインスタンス」を意味している。
- 静的フィールドへのアクセスに変更すればOK(this.→Cleric.)。静的フィールドであれば、インスタンスを1つも生み出さなくても利用可能になる。(金型の上に作られる箱)
コンパイルエラー
C:\work\ex91>javac Main.java Cleric.java Cleric.java:10: エラー: スーパータイプのコンストラクタの呼出し前はthisを参照できません this(name, hp, this.MAX_MP); ^ Cleric.java:13: エラー: スーパータイプのコンストラクタの呼出し前はthisを参照できません this(name, this.MAX_HP, this.MAX_MP); ^ Cleric.java:13: エラー: スーパータイプのコンストラクタの呼出し前はthisを参照できません this(name, this.MAX_HP, this.MAX_MP); ^ エラー3個
修正後
// コンストラクタ public Cleric(String name, int hp, int mp) { this.name = name; this.hp = hp; this.mp = mp; } public Cleric(String name, int hp) { this(name, hp, Cleric.MAX_MP); } public Cleric(String name) { this(name, Cleric.MAX_HP, Cleric.MAX_MP); }
改善③:引数で指定したHP/MPが最大値を超えないように制御
修正後
// コンストラクタ public Cleric(String name, int hp, int mp) { this.name = name; this.hp = Math.min(hp, Cleric.MAX_HP); this.mp = Math.min(mp, Cleric.MAX_MP); } public Cleric(String name, int hp) { this(name, hp, Cleric.MAX_MP); } public Cleric(String name) { this(name, Cleric.MAX_HP, Cleric.MAX_MP); }