1日目のゴール
中級編「カプセル化アプリ」1日目のテーマは
「直接触らせない」=カプセル化の感覚を体でつかむこと です。
キーワードはprivate と getter / setter。
でも、ただ「書き方を覚える」んじゃなくて、
「なぜ直接触らせないほうがいいのか」 を、
ちゃんと腑に落ちるところまで行きます。
カプセル化って、そもそも何なのか
「中身を勝手にいじらせない」という設計の考え方
カプセル化(encapsulation)は、
ざっくり言うとこういう考え方です。
「オブジェクトの中身(フィールド)を、
外から勝手にいじらせないようにする。
代わりに、“決められた窓口(メソッド)”だけを通して
触ってもらう。」
イメージで言うと、
薬のカプセルみたいなものです。
中身の粉は直接触れない。
外から見えるのは「カプセル」という殻だけ。
飲み方(使い方)は決まっている。
プログラムでも同じで、
「中身を守る殻」 を作るのがカプセル化です。
悪い例から入る:フィールドを丸出しにしたクラス
直接触れると、何が困るのか
まず、あえて「悪い例」を見てみます。
public class User {
public String name;
public int age;
}
Javaこのクラスは、name も age も public です。
つまり、どこからでもこう書けます。
User u = new User();
u.name = "Taro";
u.age = -100; // これも通ってしまう
Javaここで問題になるのは、
年齢がマイナスでも通ってしまう
ありえない値でも、誰でも勝手に入れられる
ということです。
「User の中身を守る人」がいない 状態なんです。
「直接触らせない」ための第一歩:private
フィールドを隠す=外から見えないようにする
そこで出てくるのが private です。
public class User {
private String name;
private int age;
}
Javaprivate を付けると、
そのフィールドは 「そのクラスの中からしか触れない」
というルールになります。
外側からこう書こうとすると、コンパイルエラーになります。
User u = new User();
u.name = "Taro"; // エラー
u.age = 20; // エラー
Javaこれは一見「不便」に見えるかもしれませんが、
実はめちゃくちゃ大事な一歩です。
「中身に直接触れないようにすることで、
中身を守るチャンスが生まれる」 からです。
「触る窓口」を用意する:getter / setter
ただ隠すだけじゃなく、「正しい触り方」を決める
private にしただけだと、
外から何もできなくなってしまいます。
そこで出てくるのがgetter と setter です。
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Javaこうすると、外からはこう書けます。
User u = new User();
u.setName("Taro");
u.setAge(20);
System.out.println(u.getName());
System.out.println(u.getAge());
Javaここで重要なのは、
フィールドには直接触れない
でも、決められたメソッドを通してなら触っていい
という 「ルール付きのアクセス」 に変わったことです。
重要ポイントの深掘り1:setter の中で“守り”ができる
「ありえない値」を弾けるようになる
public フィールドのときは、
誰でも好きな値を入れられました。
age = -100 も通ってしまう。
でも、setter を使うと、
その中でチェックができます。
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年齢は0以上にしてください");
}
this.age = age;
}
Javaこうしておけば、
User u = new User();
u.setAge(-100); // ここで例外が出る
Java「User の中身を守るのは User 自身」
という状態になります。
これがカプセル化の本質です。
重要ポイントの深掘り2:内部表現を後から変えられる
外から見える“顔”はそのまま、中身だけ差し替える
もう一つ、カプセル化の大きなメリットがあります。
それは、
「中身の表現を後から変えても、外側のコードを壊さなくて済む」
ということです。
例えば、最初はこう書いていたとします。
public class User {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年齢は0以上");
}
this.age = age;
}
}
Javaでも、途中で
「年齢じゃなくて、生年月日で持ちたいな」
と思ったとします。
内部をこう変えます。
public class User {
private LocalDate birthDate;
public int getAge() {
LocalDate now = LocalDate.now();
return Period.between(birthDate, now).getYears();
}
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
}
Java外側のコードはどうでしょう。
User u = new User();
u.setBirthDate(LocalDate.of(2000, 1, 1));
System.out.println(u.getAge());
Java「年齢を知りたい」という外側のニーズはgetAge() というメソッドで満たされ続けます。
「外から見えるメソッド(顔)は変えずに、
中身だけ差し替える」 ことができる。
これが、
カプセル化が保守性を上げる理由です。
例題:カプセル化アプリの超シンプル版
「ポイントカード」クラスで考えてみる
小さな「ポイントカード」クラスを作ってみましょう。
やりたいことはこうです。
ポイントを貯める
ポイントを使う
現在のポイントを確認する
でも、
「直接ポイント数をいじらせない」
という方針で設計します。
public class PointCard {
private int point;
public PointCard() {
this.point = 0;
}
public int getPoint() {
return point;
}
public void addPoint(int amount) {
if (amount < 0) {
throw new IllegalArgumentException("追加ポイントは0以上");
}
this.point += amount;
}
public void usePoint(int amount) {
if (amount < 0) {
throw new IllegalArgumentException("使用ポイントは0以上");
}
if (amount > point) {
throw new IllegalArgumentException("ポイントが足りません");
}
this.point -= amount;
}
}
Java外側からはこう使います。
PointCard card = new PointCard();
card.addPoint(100);
card.usePoint(30);
System.out.println(card.getPoint()); // 70
Javaここでのポイントは、
point フィールドは private
外からは addPoint と usePoint しか使えない
「マイナスを追加する」「残高以上を使う」などの不正操作は
クラス自身が弾いてくれる
という 「直接触らせないことで、ルールを守らせる」 設計になっていることです。
今日のまとめ:カプセル化の“感覚”
1日目で掴んでほしいのは、private と getter / setter の書き方そのものよりも、
「なぜ直接触らせないほうがいいのか」
という感覚です。
フィールドを public にすると、
誰でも好き勝手にいじれてしまう。
private にして、getter / setter を通すことで、
値のチェックができる
内部表現を後から変えられる
クラス自身が自分の中身を守れる
という状態になる。
それがそのまま
保守性=壊れにくさ・変更に強さ
につながっていきます。
次のステップでは、
「ただの getter / setter」から一歩進んで、
「振る舞いを持ったメソッド」 にしていく話にも
つなげていけます。
