より強固なメソッドにする

修飾子を設定することで,データを追加するときと,データを取り出すときには,必ず決まったメソッドを介さなければアクセスできないようにした.

オブジェクトにまとめる前のイメージオブジェクトにまとめた後のイメージ

データにアクセスするためのメソッドが入出力を厳密に検査することで,カプセル化がより強固になる. スタックの場合には,データが空か,満杯かを判断して,入出力が可能かどうか判断していた.それ以外に,入ってくるデータが妥当であるかどうかを調べて,入力を受け付けるかどうかを判断することで,オブジェクトのカプセル化がより強固になる.

今回のスタックに関しては,データが自然数である範囲で正常に動作するようにしているため,入力データとして,正常に動作する範囲の値であるかどうかを必ず検査しなければならない.

pushメソッドにおいて追加するチェックを含めると,次のようなメソッドになる.
//データ追加メソッド
public boolean push(int number)
{
    if(number > 0)
    {
        if(volume < data.length)
        {
            data[volume] = number;
            volume++;
            return true;
        }
        else
        {
            System.out.println("stack overflow");
            return false;
        }
    }
    else
    {
        System.out.println("input value invalid");
        return false;
    }
}

さらに,修飾子はメソッドにも設定することができる.そのメソッドが外のクラスから実行できる範囲を設定することができる.現在設置しているメソッドについては,外部からデータを操作するために設置しているメソッドだけであるので,privateに設定する必要のあるメソッドはない.しかし,例えば,内部で呼び出すためのサブルーチンなどがあったとき,そのメソッドを外部から実行されるようになっていては困る.そのようなときには,privateなどを設定する.そうでないときには,適切な範囲の修飾子を与える.今回は,外部から呼び出されて問題ないので,publicを設定することにする.

さらに,privateなメソッドを試すために,引数のあるprintStackメソッドは,引数の無いprintStackメソッドから呼び出される,クラス内から呼び出すためのメソッドであると設定することを想定すると,以下のようになる.

class Stack
{
    private int volume;
    private int data[];
    static int defaultSize = 5;
    //標準サイズのためのコンストラクタ
    public Stack()
    {
        this(defaultSize);
    }
    //サイズ指定のためのコンストラクタ
    public Stack(int stackSize)
    {
        data = new int[stackSize];
        System.out.println(data.length + "個分のスタック生成");
    }
    //データ追加メソッド
    public boolean push(int number)
    {
        if(number > 0)
        {
            if(volume < data.length)
            {
                data[volume] = number;
                volume++;
                return true;
            }
            else
            {
                System.out.println("stack overflow");
                return false;
            }
        }
        else
        {
            System.out.println("input value invalid");
            return false;
        }
    }
    //データ取得メソッド
    public int pop()
    {
        int value;
        if(volume > 0)
        {
            value = data[volume -1];
            data[volume -1] = 0;
            volume--;
        }
        else
        {
            value = -1;
        }
        return value;
    }
    //状態表示メソッド
    public void printStack()
    {
        System.out.print("|");
        for(int i=0; i < data.length; i++)
        {
             printStack(i);
             System.out.print("|");
        }
        System.out.println("");
    }
    //個別の状態表示メソッド
    private void printStack(int i)
    {
        System.out.print(data[i]);
    }
}

厳密に入力をチェックすることを確かめるためのコードを以下に準備する.

public class Main
{
    public static void main(String[] args)
    {
        Stack tower = new Stack(5);
        tower.push(10);tower.printStack();
        tower.push(20);tower.printStack();
        tower.push(30);tower.printStack();
        tower.push(40);tower.printStack();
        tower.push(50);tower.printStack();
        //以下を有効にすると,警告が出ることを確認する.
//      tower.data[3] = 100;
//      tower.printStack(3);
        System.out.println(tower.pop());tower.printStack();
        System.out.println(tower.pop());tower.printStack();
        System.out.println(tower.pop());tower.printStack();
        System.out.println(tower.pop());tower.printStack();
        System.out.println(tower.pop());tower.printStack();
        System.out.println(tower.pop());tower.printStack();
        tower.push(-1);
    }
}

実行した結果は以下のようになる.

5個分のスタック生成
|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|40|0|
40
|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|
input value invalid

演習

キューのプログラムについて,データを追加するメソッドにおいて,入力を厳密にチェックする処理を独立したメソッドとして設けよ.そのメソッドは,内部からのみ呼び出すことができるようにカプセル化をより強固にせよ.強固になったことを確認するために,入力が厳密にチェックされていることを確認せよ.

より強固なメソッドにする