Java アクセス修飾子を使ってカプセル化する。

Javaのようなオブジェクト指向言語では、クラスによりプログラムを部品化することで、プログラムを再利用しやすいというメリットがあります。

Javaは小さな部品単位でプログラムを作成して、部品を組み合わせることで大きなシステムを構築します。

しかしクラスを部品として再利用するには、それぞれのクラスが安定して動かなければなりません。クラスのフィールドに不正な値が設定されたりするとまずいわけです。

例えば以下のようにフィールドを他のクラスから簡単に変更できると、本来ありえない値も設定できてしまいます。

people[0].age = -15;
people[1].age = -25;

プログラムの実行結果を見ると、年齢がマイナスになっています。
java-229.gif

age はint(整数)で宣言しているので、データ型としてはマイナスが入ってもエラーにはなりませんが、年齢という意味を考えるとマイナスはおかしいですよね。

このような値が後に不具合の原因になります。これではクラスが安定して動作しているとはいえません。

そこでクラスの外部からはフィールドを直接操作できないようにして、必ずメソッドを経由してフィールドを間接的に操作するようにします。これをカプセル化といいます。メソッドを経由することで、データをチェックしてからフィールドに設定できます。

カプセル化はクラス、フィールド、メソッドに適切な「修飾子」を付けることで簡単にできます。アクセス修飾子には、public、protected、指定なし、private などがあり、クラス、フィールド、メソッドで使える修飾子が異なります。


【1】sample06 フォルダをフォルダごとコピーして、sample07 フォルダを作ります。

java-222.gif


【2】sample07 の PersonTest.java を以下のように変更します。変更のポイントはアクセス修飾子の private を付けたことです。このプログラムをコンパイルするとエラーになりますがわざとです。

保存先 C:\java\sample07
ファイル名 PersonTest.java

public class Person {
  private String name;
  private int age;
  private String address;

  public Person(String _name, int _age, String _address) {
    name = _name;
    age = _age;
    address = _address;
  }

  public void say(){
    System.out.println("私の名前は" + name + "です。年齢は"
    + age + "才で、住所は" + address + "です。");
  }

}

public class PersonTest {
  public static void main(String[] args) {
    Person[] people = new Person[2];
    people[0] = new Person("太郎", 21, "東京都港区");
    people[1] = new Person("花子", 18, "北海道札幌市");

    for(int i = 0; i < people.length; i++){
      people[i].say();
    }

    System.out.println("データを変更。");

    people[0].name = "次郎";
    people[0].age = 15;
    people[0].address = "福岡県福岡市";
    people[1].name = "桃子";
    people[1].age = 25;
    people[1].address = "宮城県仙台市";

    for(int i = 0; i < people.length; i++){
      people[i].say();
    }

  }
}



【3】以下の図を参考に、カレントディレクトリの切り替え、コンパイルを行います。このプログラムをコンパイルするとエラーになりますが、エラーメッセージからどのような問題点があるのか考えてみます。

java-223.gif

エラーメッセージが少しわかりにくいので、補足して説明します。

(1)クラス Person は public クラスなので、ファイル名は Person.java にしなければなりません。public クラスは1つのファイルに1つしか書けないからです。

(2)フィールドにアクセス修飾子の private を付けたことで、他のクラスからは直接アクセスできないというエラーです。


(3)エラーが7個あることを表しています。


つまりソースファイルをクラスごとに分けて、Personクラス側にフィールドを間接的に操作するためのメソッドを用意して、PersonTest側からはこのメソッドを呼び出すようにすれば、エラーは解決します。次回に修正してみましょう。


【解説】

実はこれまでクラス、フィールド、メソッドは簡略形で書いていました。[]カッコは省略できることを表しています。

(1)クラスの書式

・正式形
[修飾子] class クラス名[extends節][implements節] {
  内容
}

・簡略形
class クラス名 {
  内容
}


(2)フィールドの書式

・正式形
[修飾子] 変数の型 フィールド名;

・簡略形
変数の型 フィールド名;


(3)メソッドの書式

・正式形
[修飾子] 戻り値の型 メソッド名(仮引数のリスト){
  内容
  return 戻り値;
}

・簡略形
戻り値の型 メソッド名(仮引数のリスト){
  内容
  return 戻り値;
}


(4)主な修飾子

・public :すべてのクラスからアクセス可能。
・protected :同一クラス内、同一パッケージ、サブクラスからアクセス可能。
・指定なし :同一クラス内、同一パッケージからアクセス可能。
・private :同一クラス内のみアクセス可能。

*パッケージについては別の機会に説明します。今の段階では同じフォルダ内と考えてください。

これまで書いていたプログラムは「指定なし」の設定になっていました。修飾子をつけなくても同じフォルダ内のクラスだったので、PersonTestクラスからPersonクラスを利用できたのです。


スポンサードリンク

スポンサードリンク






Java初心者入門講座TOPへ