パパの勉強部屋

勉強の記録をつけています。Java、ネットワーク、Excel、etc.

スッキリわかる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);
	}