コンテンツにスキップ

プログラミング/カプセル化

出典: フリー教科書『ウィキブックス(Wikibooks)』

カプセル化

[編集]

カプセル化とは

[編集]

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

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

カプセル化の実装方法

[編集]

アクセス修飾子

[編集]

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

Java

[編集]
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;
    }
}

C++

[編集]
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;
    }
};

Rust

[編集]
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. パフォーマンスへの影響を考慮する

まとめ

[編集]

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