【2025年版】カプセル化とアクセス修飾子完全ガイド – 初心者でもわかるオブジェクト指向の基本

 

カプセル化とは?初心者向け解説

カプセル化(Encapsulation)は、オブジェクト指向プログラミングの三大要素の一つで、データ(フィールド)とそれを操作するメソッドを一つのクラスにまとめ、外部からの直接アクセスを制限する仕組みです。

カプセル化のメリット

  • データの保護:不正な値の設定を防止
  • 保守性の向上:内部実装の変更が外部に影響しない
  • 再利用性の向上:安全で使いやすいクラス設計
  • バグの軽減:制御されたアクセスによりエラーを防止

アクセス修飾子の種類と使い分け

Java のアクセス修飾子一覧

修飾子 同一クラス 同一パッケージ サブクラス 外部パッケージ
public
protected ×
default × ×
private × × ×

1. private(最も制限的)

用途:クラス内部のデータやヘルパーメソッド

public class BankAccount {
    private double balance;  // 外部から直接アクセス不可
    
    private boolean isValidAmount(double amount) {
        return amount > 0;
    }
}

2. public(最も開放的)

用途:外部に公開するメソッドやクラス

public class Calculator {
    public double add(double a, double b) {
        return a + b;  // どこからでも呼び出し可能
    }
}

3. protected(継承関係で使用)

用途:サブクラスに継承させたいメンバー

public class Animal {
    protected String name;  // サブクラスからアクセス可能
    
    protected void sleep() {
        System.out.println(name + "が眠っています");
    }
}

4. default(パッケージプライベート)

用途:同一パッケージ内でのみ共有したいメンバー

class PackageHelper {
    String getMessage() {  // 同一パッケージ内からのみアクセス可能
        return "パッケージ内メッセージ";
    }
}

カプセル化の実践例

悪い例:カプセル化されていないクラス

public class BadStudent {
    public String name;
    public int age;
    public double score;  // 直接アクセス可能 = 危険
}

// 使用例:問題のあるコード
BadStudent student = new BadStudent();
student.score = -50;  // 不正な値が設定可能

良い例:適切にカプセル化されたクラス

public class Student {
    private String name;
    private int age;
    private double score;
    
    public void setScore(double score) {
        if (score >= 0 && score <= 100) {
            this.score = score;
        }
    }
    
    public double getScore() {
        return score;
    }
}

// 使用例:安全なコード
Student student = new Student();
student.setScore(-50);  // 無効な値は設定されない

Getter/Setter パターンの実装

基本的な Getter/Setter

public class Person {
    private String name;
    private int age;
    
    // Getter
    public String getName() { return name; }
    public int getAge() { return age; }
    
    // Setter(バリデーション付き)
    public void setName(String name) {
        if (name != null && !name.trim().isEmpty()) {
            this.name = name;
        }
    }
    
    public void setAge(int age) {
        if (age >= 0 && age <= 150) {
            this.age = age;
        }
    }
}

読み取り専用プロパティ

public class ImmutableProduct {
    private final String id;
    private final String name;
    
    public ImmutableProduct(String id, String name) {
        this.id = id;
        this.name = name;
    }
    
    public String getId() { return id; }     // Getter のみ
    public String getName() { return name; } // 変更不可
}

言語別アクセス修飾子の違い

C# のアクセス修飾子

public class CSharpExample {
    private int privateField;
    protected int protectedField;
    internal int internalField;     // アセンブリ内でアクセス可能
    public int publicField;
    
    private protected int restrictedField;  // C# 7.2 以降
}

Python のカプセル化

class PythonExample:
    def __init__(self):
        self.public = "誰でもアクセス可能"
        self._protected = "慣例的にprotected"
        self.__private = "プライベート(名前修飾される)"
    
    def get_private(self):
        return self.__private

JavaScript のプライベートフィールド

class JSExample {
    #privateField;  // ES2022 プライベートフィールド
    
    constructor() {
        this.#privateField = "プライベート";
    }
    
    getPrivate() {
        return this.#privateField;
    }
}

カプセル化設計のベストプラクティス

1. デフォルトは private

public class BestPractice {
    private String data;  // まずprivateで宣言
    
    public String getData() {  // 必要に応じてアクセサを提供
        return data;
    }
}

2. 不変オブジェクトの活用

public final class ImmutablePoint {
    private final int x, y;
    
    public ImmutablePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public int getX() { return x; }
    public int getY() { return y; }
}

3. ビルダーパターンとの組み合わせ

public class User {
    private final String name;
    private final String email;
    
    private User(Builder builder) {
        this.name = builder.name;
        this.email = builder.email;
    }
    
    public static class Builder {
        private String name, email;
        public Builder setName(String name) { this.name = name; return this; }
        public User build() { return new User(this); }
    }
}

よくある間違いと対策

間違い1:すべてを public にする

// 悪い例
public class BadDesign {
    public String name;  // 直接アクセス可能
    public List<String> items;  // リストの中身を変更可能
}

// 良い例
public class GoodDesign {
    private String name;
    private List<String> items = new ArrayList<>();
    
    public List<String> getItems() {
        return new ArrayList<>(items);  // 防御的コピー
    }
}

間違い2:Getter/Setter の濫用

// 単純すぎる例
public class OverUsed {
    private int value;
    public int getValue() { return value; }
    public void setValue(int value) { this.value = value; }
}

// より良い設計
public class BetterDesign {
    private int balance;
    
    public void deposit(int amount) {  // 意味のあるメソッド名
        if (amount > 0) balance += amount;
    }
    
    public boolean withdraw(int amount) {
        if (amount > 0 && balance >= amount) {
            balance -= amount;
            return true;
        }
        return false;
    }
}

実践的な学習ステップ

初級レベル

  1. private/public の使い分けを理解
  2. 基本的な Getter/Setter の実装
  3. フィールドの直接アクセスを避ける習慣

中級レベル

  1. protected の適切な使用場面を理解
  2. 不変オブジェクトの設計
  3. 防御的プログラミングの実践

上級レベル

  1. アクセス制御とセキュリティの関係
  2. API 設計におけるカプセル化
  3. フレームワーク設計での応用

まとめ

カプセル化とアクセス修飾子は、オブジェクト指向プログラミングの基礎であり、保守性の高いコードを書くために欠かせない概念です。適切なアクセス制御により、データの整合性を保ち、クラスの責任を明確にできます。

実際のプロジェクトでは、まずデフォルトで private を使用し、必要に応じて段階的にアクセス範囲を広げる設計アプローチを推奨します。カプセル化をマスターすることで、より安全で再利用可能なコードが書けるようになります。

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<月1開催>放送作家による映像ディレクター養成講座

<オンライン無料>ゼロから始めるPython爆速講座