カプセル化

編集

カプセル化とは

編集

カプセル化(Encapsulation)は、オブジェクト指向プログラミングの基本原則の一つで、データ(属性)とその操作(メソッド)を一つのユニット(クラス)にまとめ、外部からの直接アクセスを制限する設計手法です。主な目的は、以下の通りです:

  • データの隠蔽
  • システムの複雑さの管理
  • データの不正な変更の防止
  • インターフェースの明確な定義

カプセル化の実装方法

編集

アクセス修飾子

編集

異なる言語でのアクセス制御の実装例:

public class BankAccount {
    // プライベート変数 - 直接アクセス不可
    private double balance;
    private String accountNumber;

    // パブリックコンストラクタ
    public BankAccount(String accountNumber, double initialBalance) {
        this.accountNumber = accountNumber;
        this.balance = initialBalance;
    }

    // パブリックメソッドを通じてのみアクセス可能
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    public void withdraw(double amount) throws InsufficientFundsException {
        if (amount > balance) {
            throw new InsufficientFundsException("残高不足");
        }
        balance -= amount;
    }

    // 読み取り専用のゲッター
    public double getBalance() {
        return balance;
    }
}
class BankAccount {
private:
    // プライベートメンバー
    double balance;
    std::string accountNumber;

    // プライベートヘルパーメソッド
    void logTransaction(const std::string& type, double amount) {
        // 内部ログ記録
        std::cout << "Transaction: " << type 
                  << ", Amount: " << amount << std::endl;
    }

public:
    // コンストラクタ
    BankAccount(std::string accNum, double initialBalance) 
        : accountNumber(accNum), balance(initialBalance) {}

    // パブリックインターフェース
    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            logTransaction("Deposit", amount);
        }
    }

    bool withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
            logTransaction("Withdrawal", amount);
            return true;
        }
        return false;
    }

    double getBalance() const {
        return balance;
    }
};
pub struct BankAccount {
    // デフォルトではプライベート
    account_number: String,
    balance: f64,
}

impl BankAccount {
    // パブリックコンストラクタ
    pub fn new(account_number: String, initial_balance: f64) -> Self {
        BankAccount {
            account_number,
            balance: initial_balance,
        }
    }

    // パブリックメソッド
    pub fn deposit(&mut self, amount: f64) -> Result<(), String> {
        if amount > 0.0 {
            self.balance += amount;
            Ok(())
        } else {
            Err("Invalid deposit amount".to_string())
        }
    }

    pub fn withdraw(&mut self, amount: f64) -> Result<(), String> {
        if amount > 0.0 && amount <= self.balance {
            self.balance -= amount;
            Ok(())
        } else {
            Err("Invalid withdrawal amount".to_string())
        }
    }

    // 読み取り専用メソッド
    pub fn get_balance(&self) -> f64 {
        self.balance
    }
}

プロパティとゲッター/セッター

編集

TypeScript

編集
class Person {
    // プライベートプロパティ
    private _age: number;
    private _name: string;

    constructor(name: string, age: number) {
        this._name = name;
        this._age = age;
    }

    // ゲッターとセッター
    get name(): string {
        return this._name;
    }

    get age(): number {
        return this._age;
    }

    set age(value: number) {
        if (value > 0 && value < 150) {
            this._age = value;
        } else {
            throw new Error("無効な年齢です");
        }
    }

    // バリデーションロジックを含むメソッド
    updateName(newName: string): void {
        if (newName.length > 0) {
            this._name = newName;
        } else {
            throw new Error("名前は空にできません");
        }
    }
}

スマートポインターとメモリ管理

編集

C++モダンカプセル化

編集
#include <memory>
#include <iostream>

class ResourceManager {
private:
    // スマートポインターによるリソース管理
    std::unique_ptr<int> resource;

public:
    ResourceManager() : resource(std::make_unique<int>(42)) {
        std::cout << "リソース作成" << std::endl;
    }

    // リソースへの安全なアクセス
    int getValue() const {
        return resource ? *resource : -1;
    }

    void updateValue(int newValue) {
        if (resource) {
            *resource = newValue;
        }
    }
};

カプセル化の利点

編集
  1. データの保護
  2. 内部実装の変更の容易さ
  3. コードの柔軟性と保守性の向上
  4. セキュリティの強化

カプセル化の設計ガイドライン

編集
  1. 可能な限りプライベートにする
  2. 必要最小限のパブリックインターフェースを提供
  3. 一貫性のあるデータ検証を実装
  4. 不変条件を維持する

注意点

編集
  1. 過度なカプセル化は複雑さを増す可能性がある
  2. 言語や状況に応じて適切なアプローチを選択する
  3. パフォーマンスへの影響を考慮する

まとめ

編集

カプセル化は、単なる技術的な制約ではなく、コードの品質と信頼性を向上させる重要な設計原則です。適切に実装することで、保守性が高く、安全性の高いソフトウェアを開発できます。