修飾子でデータを守る
クラスを用いることで,データとデータ操作をひとまとめにすることができた.これによって,クラス内に定義したデータに対して,クラス内から操作を行うように決めることができる.しかし,現状では,決められた操作以外に,クラス外から直接にデータを変更することができる.
試しに,リストのように追加してほしい.
class Main
{
public static void main(String[] args)
{
Stack tower = new Stack(10);
tower.push(10);
tower.push(20);
tower.push(30);
tower.push(40);
tower.push(50);
tower.push(60);
tower.data[3] = 100;
System.out.println(tower.pop());
System.out.println(tower.pop());
System.out.println(tower.pop());
System.out.println(tower.pop());
System.out.println(tower.pop());
System.out.println(tower.pop());
}
}
追加した状態で実行すると,以下の実行結果のような結果となる.本来,スタックでは,popとpush以外の操作を受け付けないことで,データ操作の順序が守られていた.順序が守られていることで,スタックのデータ構造を生かすことができた.しかし,途中にあるデータを直接操作できるようでは,データの完全性が保証されない結果となる.そこで,決められた操作以外を受け付けないような仕組みを設定する.
5個分のスタック生成 スタックサイズは5 10個分のスタック生成 スタックサイズは10 |10|0|0|0|0| |10|20|0|0|0| |10|20|30|0|0| |10|20|30|40|0| |10|20|30|40|50| 50 |10|20|30|100|0| 100 |10|20|30|0|0| 30 |10|20|0|0|0| 20 |10|0|0|0|0| 10 |0|0|0|0|0| -1 |0|0|0|0|0|
そこで,Stackクラスのフィールドにprivate修飾子をつける.
public class Stack { private int volume; private int data[]; //標準サイズのためのコンストラクタ Stack() { this(defaultSize); } //サイズ指定のためのコンストラクタ Stack(int stackSize) { data = new int[stackSize]; System.out.println(data.length + "個分のスタック生成"); } //データ追加メソッド boolean push(int number) { if(volume < data.length) { data[volume] = number; volume++; return true; } else { System.out.println("stack overflow"); return false; } } //データ取得メソッド int pop() { int value; if(volume > 0) { value = data[volume -1]; data[volume -1] = 0; volume--; } else { value = -1; } return value; } //状態表示メソッド void printStack() { System.out.print("|"); for(int i=0; i < data.length; i++) { System.out.print(data[i]); System.out.print("|"); } System.out.println(""); } //個別の状態表示メソッド void printStack(int i) { System.out.print("|"); System.out.print(data[i]+"|"); System.out.println(""); } }
この状態で,ソースコードの表示を確認すると,Mainクラスのmainメソッドからデータに直接アクセスしようとする命令において,「不可視」であるとの警告がでることが確認できる.
すなわち,直接データを触れることが妨げられていて,データが守られていることがわかる.
変数につけられる修飾子は以下である.final | 定数として使える |
private | 同じクラスのコードからのみアクセスできる |
protected | サブクラスからアクセスできる |
public | 他のクラスからアクセスできる |
static | 静的変数 |
(なし) | 同じパッケージの範囲でアクセスできる |
アクセスできる範囲を修飾子で指定できるのは,データをもつフィールドだけでなく,データを操作するメソッドについても同様である.privateを指定したメソッドについては,クラスの外から実行することができない.
このように,クラスの中を他のクラスから守ることをカプセル化と呼ぶ.この「カプセル」は,お薬の「カプセル」と同じことを意味する.お薬の場合は,カプセル内の薬を外から守っている.クラスの場合は,クラス内のデータであるフィールド,クラス内の操作であるメソッドを,クラス外から保護するために「カプセル化」する.
演習
キューのプログラムにおいて,キューのデータを用意したメソッド以外からアクセスできないように,修飾子を適切に設定せよ.設定した際には,外部からデータにアクセスできないことを確認するステートメントを記載して試すこと.確認後はコメントアウトしておくとよい.