カプセル化
Encapsulation
概要(サマリー)
カプセル化(Encapsulation)とは、プログラミング(特にオブジェクト指向)において、大切なデータとそれを動かす処理を「カプセル(クラス)」の中に一緒に閉じ込め、外部から勝手にデータを覗かれたり、書き換えられたりしないように保護する仕組みである。
たとえば、あなたが「自動販売機」のプログラムを作るとする。自販機の中には「売上金額」という極めて重要なデータ(変数)が入っている。
もしカプセル化をしていないと、外側のプログラムが直接「売上金額をゼロにする」「勝手に数字を書き換える」といった不正ができてしまい、大混乱を招く。
そこで、売上データはカプセルの中に隠し(非公開)、代わりに「お金を入れてボタンを押すと、売上を増やして飲み物を出す」という自販機専用の正しい窓口(関数)だけを外に公開する。
このように、中身をブラックボックス化して「正しい使い方だけを提供する」ことをカプセル化と呼ぶ。
詳細解説
カプセル化を実現する仕組み
多くのプログラミング言語では、「アクセス修飾子」と呼ばれるキーワードを使って、カプセル化(情報の隠蔽)をコントロールする。
- private (非公開):
クラスの内部からのみアクセス可能。外部のプログラムが直接読み書きすることはできない。大切なデータ(変数)は原則としてprivateに設定する。 - public (公開):
どこからでも自由にアクセス可能。外部に提供する操作用の窓口(メソッド)はpublicに設定する。
ゲッター(Getter)とセッター(Setter)
データを隠したままだと、「現在の値を確認したい」「正しい手続きで値を更新したい」という場合に困る。
そのため、private にしたデータを安全にやり取りするための専用の公開メソッド(ゲッター・セッター)を用意するのが一般的である。
Java によるカプセル化のコード例
public class User {
// 1. データを private で隠す
private int age;
// 2. 値を取得するためのゲッター(公開)
public int getAge() {
return this.age;
}
// 3. 値を変更するためのセッター(公開・バリデーション付き)
public void setAge(int age) {
if (age >= 0) { // マイナスの年齢を拒否するルールを適用できる
this.age = age;
}
}
}
この設計により、単に変数を書き換えるだけでなく、「年齢にマイナスの値が設定されそうになったら拒否する」といったセキュリティ・バリデーションルールをクラス側で一元管理できるようになり、プログラム全体の安全性が向上する。
AIコーディングとの関係
AIに「クラスを作って」とだけ指示すると、カプセル化を考慮せず、すべての変数を誰でも直接書き換えられる公開状態(JavaScriptではデフォルトなど)の単純なコードを生成しがちである。
カプセル化を考慮した安全で拡張性の高い設計にしたい場合は、プロンプトでカプセル化の適用やゲッター・セッターの作成を明示的に求めるとよい。
AIへ指示する際のポイント
- 「TypeScriptで、銀行口座(BankAccount)クラスを作成して。残高(balance)データは外部から直接書き換えられないようにカプセル化し、入金(deposit)と出金(withdraw)のパブリックメソッドを通じてのみ変更できるようにして」
- 「Pythonのクラス設計において、アットマークプロパティ(@property)デコレータを使って、変数のゲッターとセッター(カプセル化)をPythonらしく実装する例を教えて」
よくある勘違い
カプセル化はクラスを作ることと同じ?
異なる。
- クラス: データと処理を1つにまとめた「設計図(型)」。
- カプセル化: そのクラスの中で、データへの不適切なアクセスを「隠して制限する設計アプローチ(情報の隠蔽)」。
クラスを作ったとしても、中の変数をすべて public にして外から自由に書き換えられる状態のままであれば、それは「カプセル化が機能していないクラス」である。
なぜわざわざ隠して面倒なアクセス方法にするの?
「プログラムの修正を簡単にするため」である。
もし、変数 age が世界中の100箇所から直接書き換えられていた場合、age の名前を userAge に変更しようとすると、その100箇所すべてを修正しなければならず、バグの原因になる。
カプセル化してゲッター・セッターという窓口経由にしておけば、内部の変数名が変わっても、外部のプログラムは窓口の使い方を変えずに済み、修正がそのクラスの内部だけで完結する(依存関係の低減・疎結合)。
Pythonにはprivateがないのでカプセル化できない?
Pythonには他言語のような厳密な private キーワードはないが、慣習的な隠蔽の仕組みは存在する。
変数名の先頭に _(アンダースコア1つ) をつけると「内部で使う変数」という意味合いになり、__(アンダースコア2つ) をつけると名前修飾(マングリング)と呼ばれる仕組みによって外部からアクセスしにくくなる。
さらに @property デコレータを使うことで、ゲッター・セッターをPythonらしい簡潔な構文で実装できる。「Pythonにはカプセル化がない」のではなく、「言語仕様に合わせた異なる実現方法がある」と理解するのが正確である。
まとめ
- カプセル化は、クラス内のデータ(変数)を保護し、外部から直接書き換えさせないように隠蔽する設計。
- データの変更や取得は、公開された専用のメソッド(ゲッター・セッター)を通じて安全に行わせる。
- クラス内部の修正が外部のプログラムに影響しにくくなるため、プログラムの保守性(メンテナンス性)が向上する。
- AIに指示する際は、アクセス修飾子(private等)やバリデーションロジックを含めたクラス設計を依頼すると、堅牢なコードが得られる。
情報ソース
より詳しくAIに聞いてみよう
- オブジェクト指向プログラミングにおける「カプセル化」「継承」「多態性(ポリモーフィズム)」の3大要素について、初心者向けに違いを整理してください。
- JavaScriptで、ハッシュ記号(#)を使ったクラスのプライベート変数(カプセル化)の書き方と、ブラウザの対応状況について教えてください。
- カプセル化を行うことで、プログラム全体の「テスト(ユニットテスト)」が書きやすくなる理由を説明してください。
- C#における「プロパティ(get; set;)」の自動実装プロパティ機能を使った、スマートなカプセル化の書き方を教えてください。
- カプセル化が不十分な「データしか持たないクラス(ドメイン駆動設計におけるドメインモデル貧血症)」が、なぜシステム開発で嫌われるのか理由を教えてください。