ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
カプセル化とは何か
カプセル化はオブジェクト指向の 3 大原則(カプセル化・継承・ポリモーフィズム)の 1 つ。データ(フィールド)とそれを操作するメソッドを 1 つのクラスにまとめ、外部からの直接操作を禁止する仕組みです。
カプセル化しないとどうなる?
// ❌ カプセル化なし: 全部 public
class BankAccount
{
public float $balance = 0;
}
$acc = new BankAccount();
$acc->balance = -1000000; // 残高マイナスを誰でも設定可能!
$acc->balance = 'abc'; // 文字列代入も止められない!(型なし)
こうなると呼び出し側が不正な値を入れ放題。データの整合性をどこで担保するか不明になり、バグの温床に。
カプセル化したクラス
class BankAccount
{
private float $balance;
public function __construct(float $initial = 0)
{
if ($initial < 0) {
throw new InvalidArgumentException('初期残高は 0 以上');
}
$this->balance = $initial;
}
public function getBalance(): float
{
return $this->balance;
}
public function deposit(float $amount): void
{
if ($amount <= 0) {
throw new InvalidArgumentException('入金額は正の数');
}
$this->balance += $amount;
}
public function withdraw(float $amount): void
{
if ($amount <= 0) {
throw new InvalidArgumentException('出金額は正の数');
}
if ($amount > $this->balance) {
throw new RuntimeException('残高不足');
}
$this->balance -= $amount;
}
}
$acc = new BankAccount(1000);
$acc->deposit(500);
$acc->withdraw(2000); // ← RuntimeException
// $acc->balance = -100; // ← コンパイル/実行エラー(private)
これで残高が必ず 0 以上であることが BankAccount 内で保証されます。利用側は内部実装を気にしなくて OK。
アクセス修飾子
| 修飾子 | アクセス範囲 | 用途 |
|---|---|---|
private | そのクラス内のみ | 内部状態・補助メソッド |
protected | そのクラス + サブクラス | 継承先で使わせたい実装 |
public | どこからでも | API として公開する操作 |
| (default / package-private) | 同一パッケージ内(Java のみ) | 関連クラス間の共有 |
言語別の書き方
// Java
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
public void setAge(int age) {
if (age < 0) throw new IllegalArgumentException();
this.age = age;
}
}# Python: 慣習的に _ で「内部」を示す(強制ではない)
class User:
def __init__(self, name: str, age: int):
self._name = name
self.__age = age # __ は name mangling で _User__age に
@property
def name(self) -> str:
return self._name
@property
def age(self) -> int:
return self.__age
@age.setter
def age(self, value: int) -> None:
if value < 0:
raise ValueError('age must be >= 0')
self.__age = value// C#: Property で簡潔に
public class User
{
public string Name { get; init; } // 初期化時のみセット可
public int Age { get; private set; } // 外部から読み取り専用
public User(string name, int age)
{
Name = name;
Age = age;
}
public void Birthday() => Age++;
}
イミュータブル(不変)オブジェクト
究極のカプセル化: そもそも値を変更できないクラス。スレッドセーフ・キャッシュフレンドリ・バグが起きにくい。
// PHP 8.1+ readonly プロパティ
final class Money
{
public function __construct(
public readonly int $amount,
public readonly string $currency,
) {}
public function add(Money $other): Money
{
if ($this->currency !== $other->currency) {
throw new InvalidArgumentException();
}
// 自身を変更せず新インスタンスを返す
return new Money($this->amount + $other->amount, $this->currency);
}
}
$a = new Money(100, 'JPY');
// $a->amount = 200; // ← Error: Cannot modify readonly property
$b = $a->add(new Money(50, 'JPY')); // $b = 150 JPY (a は変わらない)
Java の record
Java 14+ の record はイミュータブルなデータクラスを 1 行で書ける構文糖:
// 自動で getter / equals / hashCode / toString / コンストラクタ生成
public record Money(int amount, String currency) {
// バリデーションは compact constructor で
public Money {
if (amount < 0) throw new IllegalArgumentException();
}
public Money add(Money other) {
if (!currency.equals(other.currency)) throw new IllegalArgumentException();
return new Money(amount + other.amount, currency);
}
}
Money m = new Money(100, "JPY");
int a = m.amount(); // 自動 getter
カプセル化の効用(なぜ必要か)
| 効用 | 具体例 |
|---|---|
| 変更耐性 | balance を int から BigDecimal に変えても、getBalance() を返り値変えるだけ。呼び出し側多数に影響しない |
| 不整合防止 | 残高マイナス・年齢負数・null など不正状態をクラス内で防ぐ |
| 影響範囲の限定 | private フィールドの変更影響はそのクラス内に限定。grep する範囲が狭くなる |
| テスタビリティ | publicな操作 (deposit/withdraw) 経由でしか状態が変わらないので、テストが書きやすい |
| 並行性 | イミュータブルなら lock 不要でスレッドセーフ |
アンチパターン: getter/setter を機械的に全フィールドに付ける
「private にして getter/setter を自動生成」はカプセル化していないのと同じ:
// ❌ アンチパターン
class User
{
private string $name;
private int $age;
public function getName(): string { return $this->name; }
public function setName(string $name): void { $this->name = $name; }
public function getAge(): int { return $this->age; }
public function setAge(int $age): void { $this->age = $age; }
}
// 結局 setName() で何でも入れられる → カプセル化の意味がない
正しいカプセル化は「ドメインの操作」をメソッドにすること。例: setAge() ではなく birthday() / changeAddress(Address) 等。
カプセル化と Tell, Don't Ask 原則
// ❌ Ask: 状態を聞いて外で判断
if ($order->getStatus() === 'PAID' && $order->getShippedAt() === null) {
$order->setShippedAt(now());
$shipping->send($order);
}
// ✅ Tell: オブジェクトに振る舞いを依頼
if ($order->canShip()) {
$order->ship($shipping);
}
FAQ
Q: protected と private、どちらをデフォルトにすべき?
A: private。継承で使いたくなった時にだけ protected に上げる方が安全です(緩める方向は楽、絞る方向は破壊的)。
Q: Python は private が無いから意味ないのでは?
A: __name(name mangling)で実質的な隠蔽は可能。何より規約による契約が重要で、_x は「触らないで」のシグナルです。
Q: イミュータブルにすると遅くなりませんか?
A: オブジェクト生成コストは確かに増えますが、ロック不要・キャッシュ可能・推論しやすさで多くの場面で合計コストは下がることが多いです。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
- オブジェクト指向の概念
- 継承の概念と必要性
- ポリモーフィズム(多様性)の概念と必要性
- 抽象クラスの概念と必要性
- インターフェースの概念と必要性
- カプセル化の概念と必要性
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Laravel キャッシュクリア完全ガイド(cache:clear / config:clear / 2026-05-18 07:42:07
- プロジェクトの作成と削除 2026-05-18 07:42:07
- インストール直後にNetbeansが反応しない 2026-05-18 07:42:07
- 動画やチャンネルの検索 2026-05-18 07:42:07
- APIキー取得方法 2026-05-18 07:42:07
- チャンネル情報の取得 2026-05-18 07:42:07
- API 入門 — Web API(REST / GraphQL / gRPC / 2026-05-18 07:42:07
- インストール(eclipseプラグイン) 2026-05-18 07:42:07
- Laravel「Dotenv values containing spaces must be surrounded 2026-05-18 07:42:07
- エラー一覧 2026-05-18 07:42:07
- curl: (51) SSL: certificate subject name '~' does not match 2026-05-18 07:42:07
- インストール方法(Windows版) 2026-05-18 07:42:07
- JSONから配列に変換 2026-05-18 07:42:07
- 処理を一定時間待つ 2026-05-18 07:42:07
- A non well formed numeric value encountered 2026-05-18 07:42:07
コメントを削除してもよろしいでしょうか?