下準備
テストドライバの導入
第15回目 (秋学期02回目) 分のテストドライバを導入する。以下の手順で行う。
- ダウンロード のページを開く (ここをクリック)
- プロジェクト「java2007」にある「test」の左側の「+」をクリック
- ツリーが展開されるので「install-libraries.xml」を右クリック
- 「実行(R)」にマウスカーソルを合わせる
- 「1 Ant ビルド」をクリック
- 「コンソール」タブに"BUILD SUCCESSFUL"と表示されれば成功
- eclipseの画面でプロジェクト「java2007」を右クリック
- メニューが表示されるので、「更新」をクリック
- "week15.zip" をデスクトップなどにダウンロード
- eclipseの画面でプロジェクト「java2007」を右クリック
- メニューから「インポート(I)」を選択
- 「インポート」ウィンドウが表示されるので、「Zip ファイル」を選択
- 「次へ(N)」をクリック
- 宛先フォルダー(L): が「java2007」になっていることを確認
- From archive file: の右側にある 「参照(R)...」をクリック
- ファイルダイアログが表示されるので、ダイアログ内に表示されたダウンロードしたファイルをダブルクリック
- 前の画面に戻るので、From archive file: のエリアに正しいパスが入力されていることを確認
- フォルダ「/」の左にチェックがついていることを確認 (ついていなければチェックボックスをクリック)
- 「警告を出さずに既存リソースを上書き」にチェックがついていることを確認 (上書きしたくないファイルがある場合はチェックを外す)
- 「終了 (F)」をクリック
第15週目テストドライバの導入に成功すると、java2007 プロジェクトの test フォルダに j2.lesson02.xml というファイルが作成される。
パッケージの作成
過去の演習を参考にして、「j2.lesson02」というパッケージを作成する。
2次元の座標を表すクラス
2次元の座標 (XY座標) を表すクラス Point を作成する。
このクラスでは、2点間の距離を計算するメソッドを用意することにする。
インスタンスフィールドの抽出
2次元座標インスタンスが持つ属性を考える。今回は直交座標系で点を表すものとして、以下のものを使用することにする。
- 2次元座標 has-a x の位置
- 2次元座標 has-a y の位置
どちらも double 型として宣言することにする。
コンストラクタの抽出
コンストラクタを考える上で一番簡単な方法は、インスタンスフィールドを全て初期化するコンストラクタについて考えることである。
先ほど、インスタンスフィールドとして、次の2つを抽出した。
- double x
- double y
これを初期化するコンストラクタとして、引数に x の初期値と y の初期値をとるようなものを考える。
すると、Point(double x, double y) というコンストラクタを用意すればよいことになる。
インスタンスメソッドの抽出
2次元座標のインスタンスメソッドを抽出するには、その「振る舞い」について考えるのであるが、2次元座標はただの概念なので本来は振る舞いを持たない。ここでは練習として、「自分と他の点との距離を求める」メソッドを用意する。
まず、戻り値型は座標を double 型で表しているので double とする。引数は「自分」と「他の点」であるが、インスタンスメソッドで「自分」は this で表せるため、引数にはとらない。そのため、「他の点」のみが引数となる。名前は distance とでもしておく。
上記より、double distance(Point) というメソッドを用意すればよいことになる。注意すべき点として、今回はインスタンスメソッドを用意するので、static をつけてはいけない。
骨格の作成
クラスの作成
以下の手順で、パッケージ「j2.lesson02」に「Point」クラスを作成する。
- 先ほど作成したパッケージ 「j2.lesson02」の上で右クリック
- マウスカーソルを「新規」に合わせる
- 「クラス」をクリック
- クラス名は Point とする
インスタンスフィールドの作成
Pointクラス内にインスタンスフィールドを作成する。
package j2.lesson02; public class Point { // x 座標 double x; // y 座標 double y; }
コンストラクタの作成
同様に、コンストラクタを用意する。
コンストラクタは戻り値を取らないため、ダミーの return 文を用意する必要はない。
package j2.lesson02; public class Point { // x 座標 double x; // y 座標 double y; // コンストラクタ public Point(double x, double y) { } }
インスタンスメソッドの作成
最後に、インスタンスメソッドを用意する。
戻り値が double 型であるため、return 0.0; というダミーの return 文を用意する。
package j2.lesson02; public class Point { // x 座標 double x; // y 座標 double y; // コンストラクタ public Point(double x, double y) { } // 自分と他の点との距離を求める public double distance(Point p) { return 0.0; } }
骨格テスト
ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。
「Pointに対する骨格テスト」 を実行する。
骨格テストを行った際に緑のバーが表示されれば、外側から見たプログラムの骨格は正しくなっている。
赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「Run」ボタンをクリックする。
メッセージ | 詳細 |
---|---|
(クラス名), existence | j2.lesson02 に対象のクラスが存在していない。パッケージやクラス名を確認 |
(メンバ名), existence | 対象の名前を持つメンバが存在していない |
(メソッド名), not static | インスタンスメソッドを作る際に static を指定している |
(メソッド名), type <T> | メソッドを作る際に戻り値の型を間違えている (正しくは <T>) |
各種の実装
今回は擬似コードを書くまでもないので、直接プログラムを書く。
擬似コードを書く必要がない理由は、コンストラクタも distance メソッドも、中身が非常に小さいためである。
コンストラクタの実装
コンストラクタは、渡された引数をそのままインスタンスフィールドに代入するだけである。引数とインスタンスフィールドの名前を揃えてあるため、プログラムは非常に簡単である。
public Point(double x, double y) { this.x = x; this.y = y; }
先頭に「this.」がついている左辺はフィールドを表し、右辺は引数を表している。
distance メソッドの実装
2点間の距離を求めるには、次の式を使えばよい。
distance メソッドでは自分自身 (x1, y1) が this で、もう一点 (x2, y2) が p であるので、上の数式は次のように読みかえればよい。
- x1 => this.x
- y1 => this.y
- x2 => p.x
- y2 => p.y
すると、次のようなメソッドになる。
// 自分と他の点との距離を求める public double distance(Point p) { double dx = this.x - p.x; double dy = this.y - p.y; return Math.sqrt(dx * dx + dy * dy); }
単体テスト
ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。
余裕があれば、JUnitを用いて単体テストを記述せよ。
Point クラス内に mainメソッドを作成し、その中に簡単なテストを記述してみる。例えば、次のような形でよい。
public static void main(String[] args) { Point p1 = new Point(1.0, 2.0); System.out.println(p1.x + ", " + p1.y); Point p2 = new Point(4.0, 6.0); System.out.println(p2.x + ", " + p2.y); System.out.println(p1.distance(p2)); System.out.println(p2.distance(p1)); }
このプログラムを実行し、各メソッドが期待通りに動いていることを確認する。確認したら、mainメソッドを消しても良い。
「Pointに対する単体テスト」 を実行する。
単体テストを行った際に緑のバーが表示されれば、各メソッドはある程度正しく作成されていると思われる。
赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「Run」ボタンをクリックする。
メッセージ | 詳細 |
---|---|
(メソッド名), 期待された結果と異なります | (メソッド名)を起動した結果が期待された結果と異なる。下記のテスト項目を参照 |
テスト項目は以下の通りである。
項目名 | 詳細 |
---|---|
Ctor | コンストラクタ(double, double) を (3.0, 4.0) で起動 |
distance | distance メソッドを this = (1.0, 2.0), p = (4.0, 6.0) で起動 |
Point クラスを使うプログラム
クラスやインスタンスを使用する練習として、Point クラスを使用するプログラムを考える。
擬似コードの作成
「プログラム全体」の擬似コード
プログラム全体の擬似コードは以下のようにする。
プログラム全体 print "x1を入力:" x1 = 入力 (double) print "y1を入力:" y1 = 入力 (double) print "x2を入力:" x2 = 入力 (double) print "y2を入力:" y2 = 入力 (double) p1 = (x1, y1) p2 = (x2, y2) print "(x1, y1)と(x2, y2)の距離は" + p1.distance(p2)
骨格の作成
クラスの作成
以下の手順で、パッケージ「j2.lesson02」に「PointAction」クラスを作成する。
- 先ほど作成したパッケージ 「j2.lesson02」の上で右クリック
- マウスカーソルを「新規」に合わせる
- 「クラス」をクリック
- クラス名は PointAction とする
擬似コードの貼り付け (骨格のみ)
作成したクラスに、各擬似コードの名前を貼り付ける。ただし、「プログラム全体」ではコンソールからの入力を行っていたため、import java.io.*; も追加する。
package j2.lesson02; import java.io.*; public class PointAction { // プログラム全体 }
mainメソッドの作成 (骨格のみ)
擬似コード「プログラム全体」に合わせて、クラス「PointAction」内にpublic static void main(String[] args) から始まるメソッドを作成する。ただし、擬似コード「プログラム全体」ではコンソールからの入力を行っていたので、throws IOExceptionをつける。
全体の骨格
ここまでのプログラムの骨格は以下のようになる。
package j2.lesson02; import java.io.*; public class PointAction { // プログラム全体 public static void main(String[] args) throws IOException { } }
骨格テスト
ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。
「PointActionに対する骨格テスト」 を実行する。
骨格テストを行った際に緑のバーが表示されれば、外側から見たプログラムの骨格は正しくなっている。
赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「Run」ボタンをクリックする。
メッセージ | 詳細 |
---|---|
(クラス名), existence | j2.lesson02 に対象のクラスが存在していない。パッケージやクラス名を確認 |
(メソッド名), existence | 指定されたメソッドが存在しない |
(メソッド名), public | メソッドを作る際に public が抜けている |
(メソッド名), static | メソッドを作る際に static が抜けている |
(メソッド名), type <T> | メソッドを作る際に戻り値の型を間違えている (正しくは <T>) |
(メソッド名), throws java.io.IOException | メソッドを作る際に throws IOException が抜けている |
プログラムへの変換
main メソッドの実装
続けて、先ほど作成した PointAction クラスの main メソッドの中身を記述する。
まずは擬似コードをコメントとして貼り付ける。
// プログラム全体 public static void main(String[] args) throws IOException { // print "x1を入力:" // x1 = 入力 (double) // print "y1を入力:" // y1 = 入力 (double) // print "x2を入力:" // x2 = 入力 (double) // print "y2を入力:" // y2 = 入力 (double) // p1 = (x1, y1) // p2 = (x2, y2) // print "(x1, y1)と(x2, y2)の距離は" + p1.distance(p2) }
これを元にプログラムを作成する。
// プログラム全体 public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); // print "x1を入力:" System.out.print("x1を入力:"); // x1 = 入力 (double) double x1 = Double.parseDouble(reader.readLine()); // print "y1を入力:" System.out.print("y1を入力:"); // y1 = 入力 (double) double y1 = Double.parseDouble(reader.readLine()); // print "x2を入力:" System.out.print("x2を入力:"); // x2 = 入力 (double) double x2 = Double.parseDouble(reader.readLine()); // print "y2を入力:" System.out.print("y2を入力:"); // y2 = 入力 (double) double y2 = Double.parseDouble(reader.readLine()); // p1 = (x1, y1) Point p1 = new Point(x1, y1); // p2 = (x2, y2) Point p2 = new Point(x2, y2); // print "(x1, y1)と(x2, y2)の距離は" + p1.distance(p2) System.out.println("(x1, y1)と(x2, y2)の距離は" + p1.distance(p2)); }
全体的には下記のようなプログラムにする。
package j2.lesson02; import java.io.*; public class PointAction { // プログラム全体 public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); // print "x1を入力:" System.out.print("x1を入力:"); // x1 = 入力 (double) double x1 = Double.parseDouble(reader.readLine()); // print "y1を入力:" System.out.print("y1を入力:"); // y1 = 入力 (double) double y1 = Double.parseDouble(reader.readLine()); // print "x2を入力:" System.out.print("x2を入力:"); // x2 = 入力 (double) double x2 = Double.parseDouble(reader.readLine()); // print "y2を入力:" System.out.print("y2を入力:"); // y2 = 入力 (double) double y2 = Double.parseDouble(reader.readLine()); // p1 = (x1, y1) Point p1 = new Point(x1, y1); // p2 = (x2, y2) Point p2 = new Point(x2, y2); // print "(x1, y1)と(x2, y2)の距離は" + p1.distance(p2) System.out.println("(x1, y1)と(x2, y2)の距離は" + p1.distance(p2)); } }
プログラムの実行
前回と同じ要領でプログラムを実行する。
プログラムの実行に成功し、順に 0.0, 0.0, 3.0, 4.0 と入力すると以下のように表示される。
x1を入力:0.0 y1を入力:0.0 x2を入力:3.0 y2を入力:4.0 (x1, y1)と(x2, y2)の距離は5.0
機能テスト
ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。
「PointActionに対する機能テスト」 を実行する。
赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「Run」ボタンをクリックする。
メッセージ | 詳細 |
---|---|
期待された結果と異なります | 出力された結果が期待された値と異なる。 |
機能テストの項目
項目名 | テストの内容 |
---|---|
sample | サンプルと同じ入力でプログラムを実行 |