スッキリわかるJava入門 第10章 カプセル化①
第10章 カプセル化①
カプセル化とは?
アクセス制御されない怖さ
不具合
- Heroクラスを使ったゲームのテスト中の不具合
- ①一度もモンスターと戦っていないのに勇者のHPがマイナス100になっている。
- 別開発者の「宿屋クラス」の不具合で「h.hp = -100;」とコーディングされていた。(コンパイルエラーにならない)
- ②冒険中にお城で会話をすると、なぜか勇者が理由もなく急死してゲームオーバーになる。
- 別開発者の「王様クラス」の不具合で「bye()」ではなく「die()」メソッドが呼ばれていた。
必要なアクセス制御
- ①Heroクラス以外からはhpフィールドに値を設定できない
- ②die()メソッドを呼べるのはHeroクラスだけ
4つのアクセス制御レベル
- Javaでは、それぞれのメンバ(フィールド及びメソッド)に対してアクセス制御の設定を行うことができる。
- ですが、それぞれのメンバに「Aクラスからの利用は許す」のように細かく指定すると、とても手間がかかってしまう。
- ざっくりと4段階からアクセス制御の方法を選ぶようになっている。
privateを利用する
必要なアクセス制御①の対応として、HPはprivateにする。
public class Hero { private int hp; String name; Sword sword; static int money; Hero(){ this("ダミー"); } Hero(String name){ this.hp = 100; this.name = name; } void sleep() { this.hp = 100; System.out.println(this.name + "は、眠って回復した!"); } }
- hpフィールドにprivateを指定したため、宿屋クラスのcheckIn()メソッドでは「hpフィールドにアクセスできない」コンパイルエラーが発生する。
- 勇者のhpフィールドが、いっさい変更できなくなる訳ではない。
- atack()やsleep()のように、同じheroクラスのメソッドからはhpフィールドにアクセスできる。
- 宿屋クラスのcheckIn()メソッドからは、勇者のsleep()メソッドを呼ぶように修正すればよい。
- privateであっても、this.~での読み書きは可能。
必要なアクセス制御②の対応として、die()はprivateにする。
- die()メソッドも、王様などほかのクラスからみだりに呼び出される事がないようにprivateにする。
- 外部のクラスからは呼び出せなくなるが、同じクラス内にあるattack()メソッドからの呼び出しは問題ない。
public class Hero { private int hp; String name; Sword sword; static int money; Hero(){ this("ダミー"); } Hero(String name){ this.hp = 100; this.name = name; } void bye(){ System.out.println("勇者は別れを告げた"); } private void die() { System.out.println(this.name + "は死んでしまった!"); System.out.println("GAME OVERです。"); } }