ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
カプセル化とは
カプセル化(Encapsulation)はオブジェクト指向プログラミングの 3 大特徴のひとつで(残り 2 つは継承とポリモーフィズム)、次の 2 つの側面を持ちます:
- データと操作の束ね: 関連するデータ(フィールド)とそれを扱うメソッドを 1 つのクラスにまとめる
- 情報隠蔽 (Information Hiding): 内部状態を外部から直接触らせず、決められたメソッド経由でのみ操作させる
後者の情報隠蔽が特に重要で、これが守られていればクラス内部の実装をいくら変えても、外部のコードは壊れません。
アクセス修飾子
| 修飾子 | 同クラス | サブクラス | 同パッケージ | 外部 |
|---|---|---|---|---|
| private | ○ | × | × | × |
| protected | ○ | ○ | ○ (Java) | × |
| (default/package) | ○ | × | ○ (Java) | × |
| public | ○ | ○ | ○ | ○ |
カプセル化していない例(悪い)
// ❌ 全フィールドが public
public class BankAccount {
public String owner;
public double balance;
}
// 外部から自由に書き換え可能
BankAccount a = new BankAccount();
a.balance = -1_000_000; // マイナス残高でも入る
a.balance += 100; // どこからでも増減可
この設計だと「残高はマイナスにならない」「2 重に引き落とせない」といったビジネスルールを守るのが不可能です。
カプセル化した例(良い)
public class BankAccount {
private final String owner;
private double balance;
public BankAccount(String owner, double initial) {
if (initial < 0) throw new IllegalArgumentException("initial >= 0");
this.owner = owner;
this.balance = initial;
}
public String getOwner() { return owner; }
public double getBalance() { return balance; }
public void deposit(double amount) {
if (amount <= 0) throw new IllegalArgumentException("amount > 0");
balance += amount;
}
public void withdraw(double amount) {
if (amount <= 0) throw new IllegalArgumentException("amount > 0");
if (amount > balance) throw new IllegalStateException("残高不足");
balance -= amount;
}
}
// 利用側
BankAccount a = new BankAccount("Alice", 1000);
a.deposit(500);
a.withdraw(300);
// a.balance = -1; ← コンパイルエラー(private)
balanceは private なので外から直接書き換えられないdeposit/withdraw経由でしか変更できず、不正な値は弾かれるownerはfinal+ private で読み取り専用(不変)
PHP での書き方
class BankAccount
{
public function __construct(
private readonly string $owner, // PHP 8.1+: readonly
private float $balance = 0.0
) {
if ($balance < 0) throw new InvalidArgumentException();
}
public function getOwner(): string { return $this->owner; }
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 > $this->balance) throw new RuntimeException("残高不足");
$this->balance -= $amount;
}
}
Python での書き方
Python には「言語レベルの private」はありませんが、慣習で _ プレフィックス + @property で実現します:
class BankAccount:
def __init__(self, owner: str, initial: float = 0):
self._owner = owner
self._balance = initial
@property
def owner(self) -> str:
return self._owner # 読み取り専用
@property
def balance(self) -> float:
return self._balance
def deposit(self, amount: float) -> None:
if amount <= 0: raise ValueError
self._balance += amount
def withdraw(self, amount: float) -> None:
if amount > self._balance: raise RuntimeError("残高不足")
self._balance -= amount
a = BankAccount("Alice", 1000)
print(a.balance) # @property のおかげでメソッド呼び出しに見えない
# a.balance = -1 # setter を定義していないので AttributeError
不変オブジェクト (Immutable Object)
カプセル化の極致が不変オブジェクト。一度作ったら状態が変えられないので、マルチスレッド安全かつバグの温床がゼロになります:
// Java の record(14+)
public record Point(int x, int y) {
public Point {
if (x < 0 || y < 0) throw new IllegalArgumentException();
}
}
// 利用
Point p = new Point(10, 20);
int x = p.x(); // getter 自動生成
// p.x = 30; ← コンパイルエラー(final)
現代言語の「データクラス」
| 言語 | 機能 | 例 |
|---|---|---|
| Java 14+ | record | record Point(int x, int y) {} |
| C# 9+ | record / init | record Point(int X, int Y); |
| Kotlin | data class | data class Point(val x:Int, val y:Int) |
| PHP 8.1+ | readonly | public readonly int $x |
| Python 3.7+ | dataclass | @dataclass(frozen=True) |
| TypeScript | readonly | readonly x: number |
カプセル化と getter/setter のアンチパターン
「全フィールドに無条件で getter/setter を生やす」のはカプセル化していないのと同じです。意味のない getter/setter は責務分割の機会を失うだけ:
// ❌ getter/setter を機械的に生やす(カプセル化の意味なし)
public class User {
private String name;
public String getName() { return name; }
public void setName(String n) { this.name = n; }
}
// ✅ 必要な操作だけ公開する
public class User {
private String name;
public String displayName() {
return name.isEmpty() ? "(no name)" : name;
}
public void rename(String newName) {
if (newName.isBlank()) throw new IllegalArgumentException();
this.name = newName;
}
}
カプセル化のメリットまとめ
- 変更耐性: 内部実装の変更が外部に伝播しない
- 不整合防止: 不正な状態に絶対ならない
- テスト容易性: 公開 API だけテストすればよい
- 並行処理安全性: 状態の出入り口を絞れる(不変なら最強)
- ドキュメント代わり: public な API がそのまま使い方
FAQ
Q: private と final の違い
A: private は可視性(外から見えるか)、final は変更可能性(再代入できるか)。両方つけると「外から見えず再代入もできない」最強の隠蔽。
Q: getter は遅い?
A: JIT が即座にインライン化するので、フィールド直接アクセスと性能差はほぼ無い。
Q: フレームワーク(JPA/Doctrine 等)が public を要求する
A: ORM はリフレクションで private にも読み書きできることが多い。アノテーション/属性次第。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子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
コメントを削除してもよろしいでしょうか?