[目次]
[その1]
[その3]
Javaによるオブジェクト指向プログラミング (その2)
今回は Java のプログラムの様々な書き方に馴染むために、人間
(Human) と学生 (Student) という2つの型(クラス)のオ
ブジェクトを設計し、簡単なクラス定義を行なう。
クラス:人間
今回は人間オブジェクトを以下のように定義することにする。
- 誕生日と名前を持つ。
- 誕生日はオブジェクト生成時に与えるか、オブジェクトを生成した日を
誕生日とする。
- 誕生日はオブジェクトが一旦生成されたら外部からは変更できない。
- 名前はオブジェクトが生成されてから与えられ、外部から変更もできる。
- 画面に表示する際には名前と誕生日(年月日)がわかるようにする。
このような性質を備えるためのクラス定義は次のようになる。(注: 説明の便宜
のため、今後プログラムリストには各行左端に行番号を記載するが、プログラム
の一部ではないので入力してはいけない。)
1| // Human.java
2| import java.util.*;
3| import java.text.*;
4|
5| class Human {
6| Date birthdate;
7| public String name;
8| static SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
9|
10| public Human (String date) throws Exception {
11| setBirthDate(date);
12| }
13|
14| private void setBirthDate (Date date) {
15| birthdate = date;
16| }
17|
18| private void setBirthDate (String date) throws Exception {
19| setBirthDate(sdf.parse(date));
20| }
21|
22| public Date birthDate () {
23| return (birthdate);
24| }
25|
26| public String birthDateString () {
27| return (sdf.format(birthdate));
28| }
29|
30| public String toString () {
31| return (name + "(" + birthDateString() +")");
32| }
33|
34| public static void main (String args[]) throws Exception {
35| Human h;
36|
37| h = new Human("1965.08.22");
38| h.name = "Tetsuo Sakaguchi";
39| System.out.println(h);
40| System.exit(0);
41| }
42| }
練習1
上のプログラムを入力し、実行してみよ。生成するインスタンスの誕生日や名前
を変えて実行してみよ。
解説
このプログラムに使用した主な要素について説明する。なお、Java で標準とし
て準備されているクラスの詳細については、[こちら]
にあるJDK のドキュメントの JDK API リファレンスなどを参照すること。
- コメント: (1行目)
-
Java ではプログラム中のコメントは「//」から行末まで、あ
るいは「/*」と「*/」で囲まれた範囲に書く。(ド
キュメントに入れるものは特に「/** … */」と書く。詳細は
javadoc を参照のこと。)
- import 宣言: (2〜3行目)
-
プログラム中で使用する他で定義されているクラスのパッケージを指定
する。通常 Java の標準 (Core) API のクラスについてはクラス名の前
に、「java.….」というパッケージ名がついている。指定す
る名前はパッケージ名まで含めたクラス名である。同じパッケージ内に
ある複数のクラスを指定する際は、ワイルドカードで指定することも可
能である。例えば、java.util.Date,
java.util.Calendar という二つのクラスを用いる際は、
「java.util.*」と記載しても良い。なお、
java.lang.*は明示しなくても宣言されていることになってい
る。
- クラス Date: (6行目ほか)
-
日付と時刻を表すために準備されている標準のクラス。パッケージは
java.util。実際に文字列表現を行なうためには
SimpleDateFormatクラスを用い、日付のうちの年などを取り
出すにはGregorianCalendarクラスを用いる。
- クラス String: (7行目ほか)
-
文字列を表すための標準クラス。パッケージはjava.lang。
- クラス SimpleDateFormat: (8行目ほか)
-
Date のオブジェクトを扱う際に文字列で表現した日付や時刻
との相互変換を行なうためのクラス。ここでは、日付のみを取り扱って
いる。パッケージはjava.text。
- public と private 宣言: (7, 10, 14行目など)
-
変数(フィールド)やクラス、メソッドを扱うことのできる範囲を指定
する。public はどこからでも誰からでもアクセスできること
を意味する。private はフィールドやメソッドであれば、他
のインスタンスなどからはアクセスできないことを意味する。指定する
対象によってその範囲が異なるので、詳細は参考書などを参照すること。
- new とコンストラクタ: (10, 37行目など)
-
new の後にクラス名と丸括弧を記載した式は、そのクラスの
インスタンスを生成し、結果として生成されたインスタンスがその式の
値となる。括弧内に記載された引数(存在しない場合もある)はそのク
ラスのコンストラクタへの引数となる。コンストラクタとは、その名称
がクラス名と同一であるメソッドであり、インスタンス生成時に呼び出
される。コンストラクタの役割は主にフィールドなどインスタンスに固
有なものの初期化である。初期化に必要なものを引数として受けとる。
- エラー(例外)処理と throws 宣言: (10行目ほか)
-
Java は高級言語であるので、エラーなどの対処のために例外処理機能
がある。詳細は略すが、エラーが起き得る式を用いるとコンパイル時に
「Exception java.…Exception must be caught, …」というエラーが
報告される(日本語で表示されるコンパイラもある)。この時は、
try 構文によってエラー時に行なう処理を記述するか、その
メソッドに「throws …Exception」などとthrows
宣言をする。後者の場合、実行時にエラーが起こると呼出し元のメソッ
ドにおいてその例外を投げることになるが、一切 try 構文で
受け取られなかった場合は、どの箇所で起きたかのエラーメッセージを
表示して終了するようになっている。
- メソッド呼び出し式: (11, 19行目など)
-
メソッドの呼び出し式は通常「変数名.メソッド名(引数)」と
なり、変数名で指定された変数に入っているインスタンスのクラスで定
義されたメソッドを呼び出す。ただし、変数名を省略することもでき、
その場合は、その式が書いてある場所に応じて適切なものが選ばれる。
多くの場合は、this, super(後述), クラス名のい
ずれかが省略されているものと見なされる。なお、static 宣
言をつけて定義されたメソッドは「クラス名.メソッド名(引数)
」の形で呼び出すことができる。
- 特別な変数 this: (プログラム中では省略)
-
今、そのメソッドを実行しているインスタンス自身を表す特別な変数で
あり、代入はできない。なお、this は記述を省略されること
も多い。
- フィールド式: (15, 38行目など)
-
フィールドをアクセスする場合は「変数名.フィールド名」と
記述する。なお、ここで変数名として this 以外が来る場合
は、通常そのフィールドはpublic 宣言されている。
- メソッド toString(): (30行目)
-
そのインスタンスを表す文字列を生成し返り値とするメソッドである。
System.out.println() ではこのメソッドを呼び出すことで、
引数に与えられたインスタンスを表示するための文字列を得ている。
- static 宣言: (8, 34行目)
-
あるクラスのインスタンスは通常複数存在する。通常フィールドは個々
のインスタンス毎に備えられる。例えば、インスタンスαのフィールド
name とインスタンスβのフィールドname は別のも
のである。static 宣言をするとそのクラスのインスタンス共
通のフィールドとして定義される。インスタンス毎に持つ必要がない値
や、一種の定数を扱うのに用いる。クラス変数と呼ばれることもある。
なお、メソッドで static 宣言された場合は、インスタンス
の生成をしなくても呼び出すことのできるメソッドとなる。(例:
main メソッド)
継承(インヘリタンス)
学生というクラスを以下のように設計したとする。
- 誕生日と名前を持つ。
- 誕生日はオブジェクト生成時に与えるか、オブジェクトを生成した日を
誕生日とする。
- 誕生日はオブジェクトが一旦生成されたら外部からは変更できない。
- 名前はオブジェクトが生成されてから与えられ、外部から変更もできる。
- 入学年月日を持つ。
- 学籍番号として、入学年の後に番号を降ったものを持つ。
- 画面に表示する際には学籍番号と名前と誕生日(年月日)がわかるよう
にする。
この場合、誕生日や名前に関しては「人間クラス」の定義とほとんど変わらない。
このような時に全く同じようなメソッドやフィールドを別に定義するのではなく、
その性質を受け継いでおき、違う部分のみを定義すれば良いという考え方がある。
このために、オブジェクト指向プログラミング言語では「継承」という機能が備
わっている。
人間 (Human) クラスを継承して定義した学生 (Student) ク
ラスは次のようになる。
1| class Student extends Human {
2| String id;
3| Date enterdate;
4| static SimpleDateFormat y2k = new SimpleDateFormat("yyyy"),
5| y1k = new SimpleDateFormat("yy");
6| static GregorianCalendar cal = new GregorianCalendar();
7|
8| public Student (String s) throws Exception {
9| super(s);
10| }
11|
12| public void enter (Date d, int number) {
13| int year;
14|
15| enterdate = d;
16| cal.setTime(d);
17| year = cal.get(Calendar.YEAR);
18| if (year > 1999) {
19| id = y2k.format(d) + Integer.toString(number + 100);
20| } else {
21| id = y1k.format(d) + Integer.toString(number + 100);
22| }
23| }
24|
25| public void enter (String d, int number) throws Exception {
26| enter(sdf.parse(d), number);
27| }
28|
29| public void enter (int number) {
30| enter(new Date(), number);
31| }
32|
33| public String toString () {
34| return (id + " " + super.toString());
35| }
36|
37| public static void main (String args[]) throws Exception {
38| Student s;
39|
40| s = new Student("1965.08.22");
41| s.name = "Tetsuo Sakaguchi";
42| s.enter("1984.04.01", 1);
43| System.out.println(s);
44| System.exit(0);
45| }
46| }
練習2
Human クラスの定義を格納したファイルを編集し、Human ク
ラスの定義の後に上の Student クラスの定義を追加せよ。追加したら、
そのファイルをコンパイルし、実行せよ。(なお、コンパイルするとクラスファ
イルが2つ生成される。実行の際指定するクラス名を間違えないようにすること。)
解説
main メソッドを見ればわかるように Student クラスでは定
義していないフィールド(name) を使用したり、他のメソッドでも
Human クラスでのみ定義したメソッドを利用したりしている。このよ
うに継承を用いると継承元となるクラス(スーパクラスと呼ぶ)で定義したフィー
ルドやメソッドを自分で備えているかのように使用することができる。(なお、
継承元をスーパクラスと呼ぶのに対して、継承先となる方をサブクラスと呼ぶ。)
- extends 宣言: (1行目)
-
クラスを定義する際に、スーパクラスを指定する。なお、
extends が省略された時はクラス「Object」がスー
パクラスとして指定されたものとして解釈される。(Java ではクラスは
Objectをルートとする木構造になっている。)
- クラス GregorianCalendar: (6行目ほか)
-
現行の西暦(グレゴリオ歴)によって年月日を定義しているクラス。
Date と組み合わせて、カレンダー的な情報を取り扱うために
準備されている。パッケージはjava.util。
- super:
-
this と同じく自分自身を表すが、呼び出すメソッドやアクセ
スするフィールドをスーパクラスの定義から探す。なお、コンストラク
タの場合は特別に「super(引数)」と記述する。これは、スー
パクラスにあるものと同じ名前のメソッドなどを定義したときに、スー
パクラスのメソッドを利用したい時に用いる。
- クラス Integer:
-
Java では整数を表すために基本型として int が存在するが、
これにはクラス定義が存在しない(クラス定義は「参照型」のみ)。そ
こで、整数を取り扱う上で文字列との変換などの様々なメソッドを準備
するために Integer というクラスがある。概ね他の基本型
(浮動小数点数、文字など)にもこのような対応するクラスが準備され
ている。パッケージはjava.lang。
宿題
- Human クラスの定義に性別を追加してみよ。
性別を与えるのはインスタンス生成時のみとし、画面に表示する際は
male/female など性別を表す文字を付与すること。
- Human クラスに現在の満年齢を返すメソッドを追加せよ。
例えば、「System.out.println(h.age());」とすれば年齢が
表示されるなど。SimpleDateFormat や
GregorianCalendarは特に使用しなくても良い。
[目次]
[その1]
[その3]
This page is written by
<saka@ulis.ac.jp>.
2002年 12月11日 水曜日 15時17分46秒 JST