カテゴリー
Java

Java(Step8-2)

クラスの基本

四角形のクラス

6つのフィールドを持つ四角形のクラスを作成しながら、クラスに対する理解を深めましょう。

クラスの独立

前記事で作成した銀行口座クラスと、それをテストするクラスは、単一のソースファイルに納められていました。しかし、小規模でない限り、クラス宣言のプログラムとそれを宣言するプログラムを単一のソースファイルに収めることは少ないです。個々のクラスを独立したソースファイルで実現するように作成しましょう。

四角形のクラスでは、以下のデータをフィールドとして持たせます。

  • 名前
  • 高さ
  • 奥行き
  • 現在位置のX座標
  • 現在位置のY座標

図で表すと下のようになります。

四角形のデータ
class RectangleInfo {
    private String name; //四角形名前
    private int width; //幅
    private int height; //高さ
    private int depth; //奥行き
    private double x; //現在位置X座標
    private double y; //現在位置Y座標
}

各フィールドの値が、状態を表します。すべてのフィールドは外部からアクセスできないように「非公開」とします。

クラスには、フィールドの他にコンストラクタとメソッドが必要です。概要は以下のようにします。

■コンストラクタ

現在位置の座標を(0, 0)にセットします。座標以外のフィールドには、引数に受け取った値を設定します。

■メソッド

  • 現在位置のX座標を調べる
  • 現在位置のY座標を調べる
  • 四角形の情報を表示する
  • 四角形の位置を動かす
this参照

まずは、コンストラクタを作りましょう。座標を原点(0, 0)にセットして、座標以外のフィールドには引数に渡された値を設定します。仮引数の名前は、フィールドの名前を使うと分かりやすくなります。宣言は以下のようになります。

RectangleInfo(String name, int width, int height, int depth){
        this.name = name; this.width = width; this.height = height;
        this.depth = depth; x = y = 0.0;
}

これらで大事なのは this です。this は、自分自身のインスタンスへの参照です。自分自身を操作するリモコンのイメージとして用います。このテクニックは以下のメリットがあります。

  • 仮引数の名前を何にするのか悩む必要が無い
  • どのフィールドに値を指定するための引数であるのが分かりやすい

ただし、コンストラクタやメソッドの中で this. を書き忘れると、フィールドではなく仮引数を表すことになってしまうので、 this. を書き忘れないように細心の注意が必要です

コンストラクタとメソッドを追加した四角形クラスのプログラムを以下に示します。

//RectangleInfo.java
//四角形管理クラス

public class RectangleInfo {
    private String name; //四角形名前
    private int width; //幅
    private int height; //高さ
    private int depth; //奥行き
    private double x; //現在位置X座標
    private double y; //現在位置Y座標

    //コンストラクタ
    RectangleInfo(String name, int width, int height, int depth){
        this.name = name; this.width = width; this.height = height;
        this.depth = depth; x = y = 0.0;
    }

    double getX(){return x;} //現在位置X座標を取得
    double getY(){return y;} //現在位置Y座標を取得

    //スペック表示
    void putSpec(){
        System.out.println("名前:" + name);
        System.out.println("幅:" + width + "cm");
        System.out.println("高さ" + height + "cm");
        System.out.println("奥行き" + depth + "cm");
    }

    //四角形の移動
    boolean move(double dx, double dy){
        double dist = Math.sqrt(dx * dx + dy * dy); //移動距離
        if(dist == 0)
            return false; //移動なし
        else{
            x += dx;
            y += dy;
            return true; //移動あり
        }
    }
}

各メソッドは、次のようになっています。

・メソッドgetX、getY

現在位置の座標を調べるためのメソッドです。各X座標、Y座標の数値を返します。

・メソッドputSpec

四角形の名前と幅、高さ、奥行きを表示するメソッドです。

・メソッドmove

四角形をX方向に dx、Y方向に dyだけ移動させるメソッドです。移動距離が0の場合はfalse、それ以外ならtrueを返します。

四角形クラスを利用するプログラム例を以下に示します。単純な表示をするだけです。

//RectangleTester1.java
//四角形クラスの利用その1

public class RectangleTester1 {
    public static void main(String[] args){
        RectangleInfo rect1 = new RectangleInfo("四角形1", 6, 4, 3);
        RectangleInfo rect2 = new RectangleInfo("四角形2", 5, 5, 5);

        rect1.putSpec(); //rect1のスペックを表示
        System.out.println();
        rect2.putSpec(); //rect2のスペックを表示
    }    
}
RectangleTester1.java実行結果

ソースファイルは、RectangleInfo.javaと同じディレクトリに入れておきましょう。そうすることで、同一ディレクトリ上のクラスファイルから自動的に読み込まれます。

次に、座標を移動するようにプログラムを作りましょう。順序は以下に沿って行います。

  1. 四角形の幅などのデータを読み込みます。
  2. 読み込んだ値を元にクラス RectangleInfo 型のインスタンス newRect を構築します。コンストラクタの働きによって、名前や幅などが読み込んだ値にセットされ、座標が(0, 0)にセットされます。続くwhile文では、現在位置の移動を対話的に繰り返します。
  3. 四角形をX方向にdx、Y方向にdyだけ移動します。移動距離が0の場合はfalseが返され、移動なしと表示されます。
//RectangleTester2.java
//四角形クラスの利用その2
import java.util.Scanner;

public class RectangleTester2 {
    public static void main(String[] args) {
        Scanner stdIn = new Scanner(System.in);

        System.out.println("四角形のデータを入力してください。");
        System.out.print("名前は:"); String name = stdIn.next();
        System.out.print("幅は:"); int width = stdIn.nextInt();
        System.out.print("高さは:"); int height = stdIn.nextInt();
        System.out.print("奥行きは:"); int depth = stdIn.nextInt();

        RectangleInfo newRect = new RectangleInfo(name, width, height, depth);

        while(true){
            System.out.println("現在の座標(" + newRect.getX() + ", " + newRect.getY() + ")");
            System.out.print("移動しますか[0…NO/1…YES]:");
            if(stdIn.nextInt() == 0) break;

            System.out.print("X方向の移動距離:");
            double dx = stdIn.nextDouble();
            System.out.print("Y方向の移動距離:");
            double dy = stdIn.nextDouble();

            if(!newRect.move(dx, dy))
                System.out.println("移動なし");
        }
        stdIn.close();
    }
}
RectangleTester2.java実行結果