クラスのインスタンスを扱う場合、これまでは、生成してからフィールドに値を格納しました。 例えば次のように書きました。
Time x = new Time(); x.hour = 13; x.minute = 15;
変数や配列では、初期化を使ってプログラムを短くしました。 インスタンスでも、コンストラクタ(constructor)というものを用いますと、初期化に相当することができます。 上記の例ですと、例えば次のように書けます。
Time x = new Time(13, 15);
コンストラクタはメソッドに似ています。 どちらも、あらかじめ定義しておき、呼び出しによってその機能が働きます。 コンストラクタとメソッドは以下の点が異なります。
void
や int
などと書いて、返り値の型を指定しました。
コンストラクタ定義では、返り値の型は指定しません。
new
を用います。
次のプログラムでは、コンストラクタを2つ定義しています。
OpeningTime.java の3行目から6行目までは、第1引数を hour
フィールドに格納し、第2引数を minute
フィールドに格納するコンストラクタです。
OpeningTimeTest.java の3行目でこのコンストラクタが呼び出され、9時30分を表すインスタンスが変数 x
に格納されます。
OpeningTime.java の7行目から10行目までは、hour
フィールドに9を格納し、minute
フィールドに0を格納するコンストラクタです。
特に断らなければ、OpeningTime
クラスのインスタンスは9時を表すということです。
OpeningTimeTest.java の4行目でこのコンストラクタが呼び出され、そのようなものが変数 y
に格納されます。
/* 1*/ class OpeningTime { /* 2*/ int hour, minute; /* 3*/ OpeningTime (int h, int m) { /* 4*/ this.hour = h; /* 5*/ this.minute = m; /* 6*/ } /* 7*/ OpeningTime () { /* 8*/ this.hour = 9; /* 9*/ this.minute = 0; /*10*/ } /*11*/ void print () { /*12*/ System.out.print(this.hour); /*13*/ if (this.minute < 10) { /*14*/ System.out.println(":0" + this.minute); /*15*/ } else { /*16*/ System.out.println(":" + this.minute); /*17*/ } /*18*/ } /*19*/ }
/* 1*/ class OpeningTimeTest { /* 2*/ public static void main (String[] args) { /* 3*/ OpeningTime x = new OpeningTime(9, 30); /* 4*/ OpeningTime y = new OpeningTime(); /* 5*/ x.print(); /* 6*/ y.print(); /* 7*/ } /* 8*/ }
b00a001@Ampere:~/java% java OpeningTimeTest 9:30 9:00 b00a001@Ampere:~/java%
コンストラクタをひとつも定義しない場合は、デフォルトのコンストラクタ classname()
が用意されます。
実は、これはインスタンスの生成のときにこれまで用いてきたものです。
クラスを設計するとき、普通はコンストラクタを用意します。
クラス定義は一般的に次のような形になります。
class classname { field declarations constructor definitions method definitions }
上記のプログラムでは、引数がなければ、7行目から10行目で定義されたコンストラクタが呼び出されます。 引数が2つならば、3行目から6行目で定義されたコンストラクタが呼び出されます。 名前が同じでも、引数の個数が異なるので区別できるのです。
メソッドでも同様のことができます。 引数の個数が異なれば、複数のメソッドに同じ名前が付けられます。 そのメソッドを呼び出すと、引数の個数に応じたメソッド定義が選ばれます。 同じ名前のメソッドやコンストラクタを複数定義することを、オーバーロード(overload)といいます。 実は、引数の個数が同じでも、引数の型で区別できればオーバーロードが可能です。 引数の形式は異なるけれど同じような処理をするメソッドは、オーバーロードすると分かりやすくなります。
次のプログラムは残り時間(分)を計算するものです。
RestTimeTest.java の6行目では、23時40分から見て23時55分までは15分あるという、正しい計算をします。
しかし7行目では、23時55分から見て0時10分まではマイナス1425分あるという、意図に反した出力になります。
日をまたぐ場合のために2引数の restMinute
メソッドを用意し、第2引数 d
が d 日後を表すことにします。
これを用いますと、8行目で、意図した通り15分あるという結果が得られます。
/* 1*/ class RestTime { /* 2*/ int hour, minute; /* 3*/ RestTime (int h, int m) { /* 4*/ this.hour = h; /* 5*/ this.minute = m; /* 6*/ } /* 7*/ int restMinute (RestTime t) { /* 8*/ return (60 * t.hour + t.minute) /* 9*/ - (60 * this.hour + this.minute); /*10*/ } /*11*/ int restMinute (RestTime t, int d) { /*12*/ return (60 * 24 * d + 60 * t.hour + t.minute) /*13*/ - (60 * this.hour + this.minute); /*14*/ } /*15*/ }
/* 1*/ class RestTimeTest { /* 2*/ public static void main (String[] args) { /* 3*/ RestTime x = new RestTime(23, 40); /* 4*/ RestTime y = new RestTime(23, 55); /* 5*/ RestTime z = new RestTime(0, 10); /* 6*/ System.out.println(x.restMinute(y)); /* 7*/ System.out.println(y.restMinute(z)); /* 8*/ System.out.println(y.restMinute(z, 1)); /* 9*/ } /*10*/ }
b00a001@Ampere:~/java% java RestTimeTest 15 -1425 15 b00a001@Ampere:~/java%
注意:
A子は財布に10,000円を入れて買い物に出かけました。 2,000円の品物と、500円の品物を3つ買いました。 財布の中を見たら6,500円ありましたが、ドルはありませんでした。
一方、B子は財布に5,000円と100ドルを入れて買い物に出かけました。 10ドルの品物を4つと20ドルの品物を買いました。 その後、1,000円の買い物もしました。 財布の中を見たら、4,000円と40ドルがありました。
この話を次のようにプログラムにしました。
このプログラムが動くように、Wallet
クラスを定義してください。
(消費税などは考えないでください。)
class WalletTest { public static void main (String[] args) { Wallet a = new Wallet(10000); a.buyYen(2000); a.buyYen(500, 3); a.print(); Wallet b = new Wallet(5000, 100); b.buyDollar(10, 4); b.buyDollar(20); b.buyYen(1000); b.print(); } }
b00a001@Ampere:~/java% java WalletTest 6500 yen 0 dollars 4000 yen 40 dollars b00a001@Ampere:~/java%
今日の演習10にしたがってJavaプログラムを作成し、konishi@twcu.ac.jpあてにメールでそのプログラムを提出してください。 メールには、学生番号、氏名、科目名、授業の日付けを明記してください。