3秒でわかる
クラスの中身をどこから触れるかを決めるキーワード。public と private を使い分けて、壊されたくない部分を外から隠すために使います。
もう少し詳しく
どういうものか
アクセス修飾子は、クラスやフィールド、メソッドに付けて、どの範囲のコードからアクセスできるかを指定するキーワードです。Java では public、protected、無指定(パッケージプライベート)、private の 4 段階があります。
範囲は下記の順に狭くなります。
public どこからでも
protected 同じパッケージ + サブクラス
(無指定) 同じパッケージのみ
private 同じクラス内のみTypeScript にも public、protected、private があります。ただし TypeScript のものはコンパイル時の検査だけで、生成された JavaScript には残りません。実行時にも隠したい場合は #field という private フィールド記法を使います。
なぜ必要か
フィールドを public にすると、外部のどのコードからでも代入できます。残高を持つクラスの balance が public なら、入出金メソッドを通さず負の値を直接書き込めてしまいます。書き込み口をメソッドだけに絞れば、そこに検査を 1 つ置くだけで不正な状態を防げます。
もう 1 つは変更のしやすさです。private なフィールドは外から参照されていないと保証できるため、型を変えても名前を変えても影響はクラス内に閉じます。public にした瞬間、それは他人と交わした約束になります。
具体例
public class BankAccount {
private int balance; // 外から直接触れない
public BankAccount(int initial) {
if (initial < 0) throw new IllegalArgumentException("初期残高が負です");
this.balance = initial;
}
public void withdraw(int amount) {
if (amount <= 0) throw new IllegalArgumentException("金額が不正です");
if (amount > balance) throw new IllegalStateException("残高不足です");
balance -= amount;
}
public int getBalance() {
return balance;
}
}account.balance = -500; はコンパイルエラーになります。残高を変える道は withdraw だけなので、検査を回避できません。
つまずきやすいところ
Java で修飾子を書き忘れると public にはならず、パッケージプライベートになります。同じパッケージ内では動くのに、別パッケージから使うと突然コンパイルが通らなくなるのはこれが原因です。
もう 1 つは、private にしたうえで getter と setter を機械的に全フィールドへ付ける習慣です。setter が全部あるなら public フィールドと保護の強さは変わりません。外から変えて良い値だけに setter を用意します。
似た用語との違い
| 用語 | 内容 |
|---|---|
| アクセス修飾子 | 可視範囲を指定する言語機能 |
| カプセル化 | 内部を隠して操作をメソッドに集約する設計の考え方 |
| final | 再代入や継承を禁じる。可視範囲とは別の軸 |
覚え方
既定は private から始め、外に見せる必要が出たものだけ public に上げます。逆向きに狭めるのは後から難しくなります。