新人エンジニア研修で知っておきたいカプセル化の使い方

なぜ、カプセル化の理解が重要なのか、その理由。

この記事では、弊社の新人エンジニア研修の参考にJavaを解説します。

前回は継承(拡張)について解説しました。今回はカプセル化について解説します。

カプセル化はデータ隠蔽とセットなのでデータ隠蔽についてもお話しします。これらもオブジェクト指向特有の概念です。

カプセル化とは、関連する情報と処理を1つにまとめることですオブジェクト指向はプログラムを部品と考えて、その部品の組み合わせで大きなプログラムを作るのです。物理的なモノの世界ではエンジン廻りだけを取り替える、デスクトップパソコンの電源ボックスだけを取り替えるということが可能です。例えば、車でもパソコンでも関連する部品は近くに配置されていますね。物理的なモノの場合は、距離の問題がありますから、関連の近いものを、近いところに並べるというのは自然です。しかし、情報の世界はそうではありませんから、気をつけないとグチャグチャになりがちです。そこでカプセル化が重要になります。

データ隠蔽とは、クラスのメンバ(フィールドやメソッド)の公開範囲をできるだけ限定することです。私たちは個々の部品、車やパソコンの中身(やそのデータ)に直接触れることができるでしょうか?もちろん、強引にやれば可能ですが(良い子の皆さんはぜひ試してみてください)保証適用外になりますね。逆に言えば、中身に直接触れさせないことによって部品と更には皆さんを守っていると言うこともできます。このイメージがデータ隠蔽です。

この記事では、カプセル化にデータ隠蔽の意味も含めて解説します。


情報隠蔽とカプセル化の基本

まずは、それぞれの言葉の意味を簡単に整理しておきましょう。

カプセル化とは?

カプセル化とは、関連するデータ(フィールド)と処理(メソッド)を1つの単位(クラス)にまとめることです。この仕組みによって、データとそれを操作する処理が密接に結び付けられます。

たとえば、人物を表すクラスなら、「名前」や「年齢」といったデータを1つにまとめ、そのデータを操作する処理を同じクラスに定義します。


情報隠蔽とは?

情報隠蔽とは、クラスの内部データや処理を外部から見えないように隠すことです。これを実現するために、クラスのメンバー(フィールドやメソッド)に「アクセス修飾子」を使います。

C#でよく使うアクセス修飾子には次の3つがあります。

  • public: 外部からアクセス可能
  • private: クラスの内部だけでアクセス可能
  • protected: クラスとその派生クラスからアクセス可能

情報隠蔽においては、フィールドはできるだけprivateにし、外部から直接アクセスさせないことが基本です。


情報隠蔽とカプセル化の実践

次に、実際のコードでこれらをどう実現するのかを見てみましょう。

フィールドを隠す

以下のコードは、Personクラスで情報隠蔽とカプセル化を実現した例です。

public class Person
{
    // フィールドをprivateにして隠す
    private string name;
    private int age;

    // プロパティを通じてアクセスを制御する
    public string Name
    {
        get { return name; }
        set 
        { 
            if (!string.IsNullOrEmpty(value))
            {
                name = value;
            }
            else
            {
                throw new ArgumentException("名前は空にできません。");
            }
        }
    }

    public int Age
    {
        get { return age; }
        set
        {
            if (value >= 0)
            {
                age = value;
            }
            else
            {
                throw new ArgumentException("年齢は0以上でなければなりません。");
            }
        }
    }
}

このコードのポイント

  1. フィールドをprivateにして外部から隠している
    これにより、他のプログラムから直接フィールドにアクセスして不正な値を設定されることを防げます。
  2. プロパティでアクセスを制御している
    getでフィールドの値を取得でき、setで値を設定できます。この際に、バリデーション(条件チェック)を組み込むことができます。

プロパティの自動実装

簡単な場合は、C#の「自動実装プロパティ」を使うことで、もっと短く記述できます。

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

ただし、値の検証が必要な場合は、手動でgetsetを記述するほうが良いです。


情報隠蔽の効果

情報隠蔽を実践することで、以下のような効果が得られます。

  1. 設計者が意図しない操作を防げる
    フィールドをprivateにすることで、クラスの使用者が直接操作するのを防ぎます。たとえば、Personクラスのageに不正な値(例: -10)が直接代入されることがありません。
  2. クラス内部の構造変更が容易になる
    情報隠蔽を行うと、クラスの内部構造を後から変更しても外部に影響を与えにくくなります。

クラス設計の基本原則

C#でクラスを設計するときには、以下の点に注意すると良いでしょう。

  1. フィールドはprivateにする
    必要に応じてプロパティやメソッドを通じて外部に公開します。
  2. プロパティを活用してアクセスを制御する
    バリデーションを組み込むことで、データの整合性を保てます。
  3. 責務を明確にする
    1つのクラスが多くの役割を持たないようにします(単一責任の原則)。
  4. 「is-a」か「has-a」を判断する
    継承(is-a)よりもコンポジション(has-a)の方が適切な場合があります。

まとめ

情報隠蔽とカプセル化は、プログラムの保守性や安全性を向上させる重要な概念です。C#では、privateフィールドやプロパティを活用して、クラス内部のデータをしっかり守りながら柔軟に設計できます。最初は少し面倒に感じるかもしれませんが、実践を重ねるうちにその効果を実感できるはずです。

これを機に、情報隠蔽とカプセル化を意識したクラス設計を試してみてくださいね!

今回はカプセル化について見てきました。

カプセル化することでオブジェクトは堅牢になるのでした。

前回見た、継承とポリモーフィズム、そして今回のカプセル化の3つをあわせてオブジェクト指向の三大要素と呼ばれることがあります。

<まとめ:隣の人に正しく説明できたらチェックを付けましょう>

□ カプセル化とは、関連する情報(データ)とそれに対する処理(メソッド)を1つにまとめ、クラスとして構築することである。これにより、データと処理が密接に結び付き、設計がシンプルかつ分かりやすくなる。

□ データ隠蔽とは、クラスのメンバー(フィールドやメソッド)の公開範囲を必要最低限に限定することである。アクセス修飾子を使用して、外部からの不要な操作を防ぎ、クラスの内部構造を保護する。

「フィールドの値を更新するときには必ずプロパティやメソッドを介して行い、フィールドには直接アクセスさせないこと」がデータ隠蔽の基本的な実践である。C#では、プロパティ(getとset)を使用してこれを実現する。

□ 他のプログラマに設計者が意図しない操作をさせないことがデータ隠蔽の最大の効果である。これにより、クラスの利用方法が制約され、意図しない不正な値の設定や、予期しない動作を防ぐことができる。

□ C#の基本的なクラス設計においては、フィールドはprivateまたはprotectedに設定し、外部からアクセスが必要な場合は、プロパティをpublicにすることが推奨される。

以上、今回は「カプセル化と情報隠蔽で部品の完成度を高める」方法について見てきました。

次回は、「例外処理で想定外の事態に強いシステムにする」です。

例外処理を使って、途中で落ちてしまわない頑強なプログラムを作っていきましょう。

カプセル化と情報隠蔽で部品の完成度を高める 最後までお読みいただきありがとうございます。