はじめに
オブジェクト指向の基本原則である「カプセル化」は、単にデータを private
にして隠すだけではありません。その真の目的は、クラスを安全で使いやすい「部品」として成立させることにあります。
カプセル化の活用法は、大きく以下の2つのパターンに分けられます。
- データの保護: メンバ変数へのアクセスを制限し、不正な値が設定されるのを防ぐ。
- 実装の隠蔽: クラスの内部だけで使われる複雑な処理を隠し、利用者にシンプルな操作方法だけを提供する。
この記事では、これら2つの重要なカプセル化の活用パターンを、具体的なサンプルコードと共に解説します。
パターン1: ゲッター/セッターによるデータの保護
メンバ変数を private
にし、その値を読み書きするための public
なメンバ関数(ゲッターとセッター)を公開する、最も基本的なカプセル化のパターンです。
セッター関数の中にバリデーション(値の検証)ロジックを組み込むことで、メンバ変数に不正な値が代入されるのを防ぎ、オブジェクトの状態を常に正常に保つことができます。
サンプルコード
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
int score; // 0点から100点までの値のみを許可したい
public:
// セッター (値を設定する)
void setScore(int s) {
if (s >= 0 && s <= 100) {
score = s; // 条件を満たす場合のみ値を設定
} else {
cout << "[エラー] 点数は0点から100点の範囲で設定してください。" << endl;
}
}
// ゲッター (値を取得する)
int getScore() {
return score;
}
};
int main() {
Student studentA;
studentA.setScore(85); // OK
cout << "現在の点数: " << studentA.getScore() << endl;
studentA.setScore(999); // NG (エラーメッセージが表示され、値は変更されない)
cout << "現在の点数: " << studentA.getScore() << endl;
return 0;
}
解説: score
変数は private
なので、外部から直接 studentA.score = 999
のように代入することはできません。必ず setScore
メソッドを経由する必要があり、そこで不正な値がブロックされます。
パターン2: 内部ロジックの実装を隠蔽
クラスの利用者に公開する必要のない、内部的な補助関数などを private
にすることで、クラスのインターフェース(操作方法)をシンプルに保ちます。
利用者は、公開された public
な関数を呼び出すだけで、その裏側でどのような複雑な処理が行われているかを意識する必要がなくなります。これにより、クラスが非常に使いやすくなります。
サンプルコード
#include <iostream>
#include <cmath> // sqrt (平方根) を使うために必要
using namespace std;
class Circle {
private:
// 内部でのみ使う補助関数 (private)
double calculateArea(double r) {
return r * r * 3.14159;
}
public:
// 外部に公開するインターフェース (public)
void showAreaFromDiameter(double diameter) {
if (diameter < 0) {
cout << "直径は正の値である必要があります。" << endl;
return;
}
double radius = diameter / 2.0;
// 内部の補助関数を呼び出す
double area = calculateArea(radius);
cout << "直径" << diameter << "の円の面積は " << area << " です。" << endl;
}
};
int main() {
Circle c;
// 利用者は、直径を渡すだけで面積が計算されることだけを知っていればよい
c.showAreaFromDiameter(10.0);
// 内部の calculateArea 関数を直接呼び出すことはできない
// c.calculateArea(5.0); // エラー! calculateAreaはprivateです
return 0;
}
解説: Circle
クラスの利用者は、「直径から面積を求める showAreaFromDiameter
」という機能だけを知っていればよく、半径を求めてから面積を計算するという内部的な実装の詳細を気にする必要はありません。
まとめ
今回は、カプセル化の2つの重要な活用パターンを解説しました。
- データ保護: セッター関数で値を検証し、オブジェクトの不整合を防ぐ。
- 実装の隠蔽: 複雑な内部処理を
private
にし、利用者にシンプルな操作方法を提供する。
これらのパターンを適切に使いこなすことで、オブジェクトの安全性を高め、かつ利用者が直感的に使える「優れた部品」としてのクラスを設計することができます。