データと操作を1つにまとめ外部から内部を隠す仕組み。
カプセル化とは、関連するデータ(属性)とそれを扱う操作(メソッド)を1つのオブジェクトにまとめ、外部から内部を直接触れないように隠す仕組みのことです。「カプセル=中身を包む殻」と考えると分かりやすいです。
外部からは、オブジェクトが公開している窓口(メソッド)を通してしか操作できません。中のデータに直接手を出すことはできないようにしておきます。
身近な例で考えると、銀行のATMに似ています。あなたは金庫(内部データ)を直接開けられず、「入金」「出金」というボタン(窓口)を通してだけお金を動かせます。上の図解で、窓口経由はOK・直接アクセスは禁止される様子を確認してください。
カプセル化の中心にある考え方が情報隠蔽(=オブジェクトの内部の作りを外部から隠すこと)です。内部データを外部から見えない(触れない)状態にし、決められた窓口を通してしか操作させません。
内部データにはprivate(=そのクラスの中からしか使えない、という指定)を付けて隠します。外部に見せたい操作だけにpublic(=どこからでも使える、という指定)を付けて公開します。
情報隠蔽には、主に次の役割があります。
・不正な値を防ぐ:窓口の中で「マイナスの残高は許さない」などのチェックをしてから更新できる
・内部の変更を外に隠す:データの持ち方を変えても、窓口の使い方が同じなら外部に影響しない
・使い方を分かりやすくする:外部は公開された窓口だけ覚えればよい
カプセル化によって、プログラムには大きく次のような利点が生まれます。
・安全性が高まる:外部から内部データを勝手に書き換えられず、不正な値の混入を防げます
・保守しやすい:内部の作りを変えても、窓口の使い方さえ同じなら外部のプログラムに影響しません
・使いやすい:利用者は内部の細かい仕組みを知らなくても、公開された窓口だけ覚えれば使えます
・整合性を保てる:窓口の中で値のチェックを行えるので、データが常に正しい状態に保たれます
身近な例で考えると、自動販売機のようなものです。利用者はお金を入れてボタンを押すだけ。中の在庫管理やお釣りの計算(内部)がどう変わっても、使う側は同じ操作のままで済みます。これがカプセル化のうれしさです。
カプセル化が必要な理由は、データを「むき出し」にすると誰でも自由に書き換えられ、プログラムが壊れやすくなるからです。たとえば銀行残高(balance)に直接アクセスできる状態だと、balance = -99999 のような不正な値が誰でも書き込めてしまいます。
カプセル化して窓口(メソッド)経由にすれば、窓口の中で「マイナスになるなら拒否する」などのルールを入れられます。つまりカプセル化とは、データを守るための「門番」を置く仕組みです。
・カプセル化なし:データがむき出し → 誰でも直接いじれる → バグや不正値が混入しやすい
・カプセル化あり:窓口を通す → 門番がチェック → 正しい値だけが内部に届く
たとえば、コンビニのレジを想像してください。お客さんが直接レジの中に手を入れてお釣りを取ることはできません。店員(窓口)を通すことで、金額が正しく管理されます。カプセル化もまったく同じ考えです。
カプセル化は、オブジェクト指向プログラミング(OOP)の3大要素のうちの1つです。残り2つは継承(既存クラスの性質を子クラスが引き継ぐ仕組み)と多態性(ポリモーフィズム)(同じ呼び出しで型ごとに違う動作をさせる仕組み)です。
3つの中でカプセル化が担う役割は「データと操作を安全にまとめる土台」です。継承でクラスを再利用したり、多態性で柔軟な呼び出しをしたりするには、まず個々のオブジェクトが正しい状態を保っている必要があります。カプセル化はそれを保証する最初の砦(とりで)です。
・カプセル化:データを守り、各オブジェクトを健全な状態に保つ
・継承:共通部分を親クラスにまとめてコードを再利用する
・多態性:型ごとの動作を統一した呼び出しで扱い、拡張しやすくする