カプセル化とは

オブジェクト指向では、オブジェクトのデータと処理をクラスの中にまとめて定義します。しかし、外部からオブジェクトのデータを直接変更できるようにすることは、あまり望ましくありません。そこで、データはメソッドを通してのみアクセスできるようにするのが一般的です。このような仕組みをカプセル化と呼びます。ここではオブジェクト指向におけるカプセル化について解説します。

カプセル化とは

オブジェクト指向では、オブジェクトが持つデータ(フィールド)とそのデータを操作する処理(メソッド)をクラスの中にまとめて定義します。オブジェクトが持つデータを外部から直接変更できるようにすることもできますが、後で説明するように問題となる場合があります。

そこで、オブジェクトのデータは外部から直接変更できないようにします。そして、データを変更するための操作をクラス内に用意し、それを外部から呼び出すようにします。このような仕組みをカプセル化と呼びます。カプセル化によってオブジェクトのデータに予期せぬ値が設定されることがないように管理できます。

フィールドを直接操作する問題

例として次のようなクラス Product を定義しました。このクラスには name と price という 2 つのフィールドがあります。

public class Sample {
  public static void main(String[] args) {
    // ・・・
  }
}

class Product {
  String name;
  int price;
}

クラスのフィールドやメソッドにはどこからアクセスできるのかを指定することができます。アクセス修飾子と呼ばれるもので public や private などを指定します。今回のように何も指定していない場合は、デフォルトの設定である「同じパッケージ内にあるクラスからのみアクセス可能」という状態になります。

詳しい説明は別のところで行いますので、 name と price フィールドは同じパッケージ内であれば外部からアクセスできる状態になっているとお考えください。

このようにフィールドが外部からアクセスできる状態になっていると、クラスの外からフィールドに値を設定することができます。

public class Sample {
  public static void main(String[] args) {
    Product p = new Product();
    p.price = -100;
  }
}

class Product {
  String name;
  int price;
}

今回 main メソッドの中で Product クラスのオブジェクトを作成したあと、オブジェクトの price フィールドに値を設定しています。本来このフィールドには負の値を設定すべきではないのですが、外部から値を直接設定できるとどんな値であっても設定が可能となってしまいます。

privateを使ったカプセル化

このような問題を防ぐために、フィールドには外部から直接アクセスできないように制限を設定します。具体的には先ほど簡単にご紹介したアクセス修飾子をフィールドに設定します。外部からのアクセスを行えないようにするには private を設定します。

class Product {
  private String name;
  private int price;
}

private を付けたフィールドは、同じクラスの中からしかアクセスできなくなります。そのため、先ほどと同じようにクラスの外からフィールドに値を設定するプログラムを作成すると、コンパイルの時点でエラーとなります。

public class Sample {
  public static void main(String[] args) {
    Product p = new Product();
    p.price = -100;
  }
}

class Product {
  private String name;
  private int price;
}

privateを使ったカプセル化(1)

ではフィールドの値を変更したり取得するにはどうすればいいかというと、同じクラス内でデータの変更や取得を行うメソッドを用意します。

class Product {
  private String name;
  private int price;

  void setPrice(int price) {
    if (price >= 0) {
      this.price = price;
    }
  }

  int getPrice() {
    return price;
  }
}

フィールドに private が付けられていても同じクラス内からであればアクセスが可能です。そこでデータの変更を行う setPrice メソッド、データの取得を行う getPrice メソッドをクラス内に定義しました。このメソッドはアクセス修飾子が設定されていないので同じパッケージ内からであればメソッドを呼び出すことができます。

クラスとオブジェクトの違い(1)

setPrice メソッドでは、フィールドに設定する値が正の数かどうかをチェックしてから設定を行っています。このように直接フィールドの値を変更できる場合と比較して、設定できる値に制限を行うことが可能となります。

getterとsetter

フィールドの値を取得するメソッドを getter、値を設定するメソッドを setter と呼びます。

getter  : フィールドの値を取得するメソッド
setter  : フィールドの値を設定するメソッド

先ほどのサンプルでいえば getPrice メソッドが getter、 setPrice メソッドが setter です。 ggetter や setter を使用することで、フィールドへのアクセス方法を制御することができます。

-- --

オブジェクト指向におけるカプセル化について解説しました。

( Written by Tatsuo Ikura )

プロフィール画像

著者 / TATSUO IKURA

これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。