ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子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
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- 【django】ログイン 認証機能 2026-09-08 03:22:09
- MySQL ERROR 1063 Incorrect column specifier for column|原因と直し方 2026-09-08 03:11:09
- 【PHPエラー】Object of class stdClass could not be converted to string 2026-09-07 07:46:04
- Julia Genie ローカル開発サーバ起動完全ガイド 2026-09-07 07:46:04
- Wi-Fi とは|規格と世代(Wi-Fi 4〜7)・周波数帯・CSMA/CA・WPA3 NEW 2026-09-07 07:45:13
- set コマンドでシェルオプションと位置パラメータを操作 | bash 2026-09-07 07:45:13
- JPEG(.jpg/.jpeg)画像形式の完全ガイド — 仕様・マジックナンバー・他形式との比較・EXIF 2026-09-07 07:45:13
- UE5 Get Overlapping Actorsで特定クラスだけ処理|Class Filter・Cast To 2026-09-07 07:45:13
- Linuxで特定拡張子のファイルを再帰削除|find -deleteの安全手順 2026-09-07 07:45:13
- Django CBVでテンプレートに値を渡す|get_context_data・extra_context 2026-09-07 07:45:13
- Linuxで複数ファイルの文字列を一括置換|find・sed・xargsの安全手順 2026-09-07 07:45:13
- Laravelルートグループ|prefix・middleware・nameで一括管理 2026-09-07 07:45:13
- Linux whichコマンドの使い方|絶対パス取得とtype・command -vの違い 2026-09-07 07:45:13
- Linux catコマンドの使い方|行番号表示・複数ファイル連結 2026-09-07 07:45:13
- unable to execute 'gcc': No such file or directory 2026-09-07 07:45:13
コメントを削除してもよろしいでしょうか?