7. 1 オブジェクト 7. 2 クラス 7. 3 インスタンス 7. 4 練習問題 7. 5 メソッド 7. 6 練習問題 7. 7 コンストラクタ 7. 8 練習問題 7. 9 変数の種類 7.10 ボールを動かす 7.11 練習問題 7.12 練習問題 7.13 練習問題 7.14 宿題 7.15 おまけ
プログラミング言語にはいろいろな種類がありますが、その中にオブジェクト指向プログラミング言語(object oriented programming language)と呼ばれるものがあり、Java 言語もその一つです。これは、計算の単位としてオブジェクトと呼ばれるものを使います。
オブジェクト(object)とは、いくつかのデータやメソッドをまとめて一塊にしたものです。小さなプログラムを作るときはそれほど便利さを感じませんが、大きなプログラムを作るときは、オブジェクトに分割することによって見通しが良くなるので重要です。
今までのプログラムでも、実はオブジェクトを使っていました。図形を描くときに使う g という変数の中身はオブジェクトです。これを次のような図で表します。
オブジェクトも、整数や文字列と同じように代入できます。
h = g;を実行すると、次の図のようになります。
オブジェクトは、プログラムとしてソースファイルの中に書くものではありません。ソースファイルの中に書くのはクラス(class)です。
例として前回の各国データを考えてみましょう。国名は文字列、人口と GDP は整数なので、一つの配列にすることはできません。三つの配列に分けて記憶しますが、データを修正したり、種類を増やしたりするのが不便です。そこで、一つの国のデータは、一つのオブジェクトにまとめてしまいましょう。
それぞれのオブジェクトは別のデータを記憶していますが、全く違うデータではなく、「国名(文字列)、人口(整数)、GDP(整数)の三つのデータを持つ」という規則に従っています。この規則を書いたものがクラスで、逆に言えばクラスの規則に従っていれば、他の国のデータをどんどん追加することができます。
「国名(文字列)、人口(整数)、GDP(整数)の三つのデータを持つ」クラスNation をプログラムの形で書くと次のようになります。
class Nation { String name; int population; int gdp; }
これをクラス宣言と呼び、一般には次の形になります。
class クラス名 { クラス本体 }
クラス名は、変数名やメソッド名と同じ付け方ならば、どんな名前でも構いません。変数名と区別しやすいように、大文字で始めるのが習慣です。
あるクラスに対して、その規則に従ってデータを記憶しているオブジェクトを、そのクラスのインスタンス(instance)と呼びます。大雑把に言えば、クラスが集合を表していて、インスタンスはその中の具体例です。
インスタンスは、データを覚えておくための変数をいくつか持つことができます。これをインスタンス変数(instance variable)と呼びます。同じクラスのインスタンスは、同じ名前のインスタンス変数を持ちますが、変数が記憶しているデータはインスタンスごとに違います。例えば、クラス Nation のインスタンスは name, population, gdp の三つの変数を持ちます。
インスタンスは、プログラムを実行した結果としてできるものです。クラス Nation のインスタンスを作るには、次の式を実行します。
7.3 インスタンス
new Nation()
できたインスタンスは、どこかに記憶しておかないといけないので、変数x に代入することにします。
x = new Nation();
変数は、まず型を宣言しなければいけないのでした。インスタンスを記憶する変数は、そのクラス名を型にします。
Nation x = new Nation();これでインスタンスはできましたが、まだ中身は何も入っていません。インスタンス変数にアクセスするには、「インスタンスを記憶している変数名(正確にはインスタンスを値とする式)」+「ピリオド」+「インスタンス変数名」とします。
Nation x = new Nation(); x.name = "United Kingdom"; x.population = 58201; x.gdp = 1102658;
「インスタンスを記憶している変数名」は、複数のインスタンスがあるときに、どのインスタンスのデータかを指定するために必要です。
Nation x = new Nation(); x.name = "United Kingdom"; x.population = 58201; x.gdp = 1102658; Nation y = new Nation(); y.name = "Egypt"; y.population = 64466; y.gdp = 60436;
クラス | インスタンス |
---|---|
国 | イギリス、エジプト、インド、… |
北海道、東京、京都、沖縄、… | |
SFCの学生 |
オブジェクトはデータを記憶するだけでなく、そのデータを使って計算を行うことができます。計算のやり方を指定するのがメソッドです。メソッド宣言は、クラス宣言の中に
Nation クラスに、一人当たり GDP を計算するメソッドを付け加えてみましょう。
class Nation { String name; int population; int gdp; double gdpPerPerson () { return (double)gdp / (double)population; } }
このメソッドを呼び出す時は、インスタンス変数と同じように「インスタンス」+「ピリオド」を前に付けます。
Nation x = new Nation(); x.name = "United Kingdom"; x.population = 58201; x.gdp = 1102658; int a = x.gdpPerPerson();
同じインスタンスの中のメソッドを呼び出す時は、「インスタンス」+「ピリオド」を前に付けなくても構いません。前回までのプログラムで、自分で作ったメソッドをメソッド名だけで呼び出していたのは、同じインスタンスの中にあるからです。
前の練習問題で作った学生クラスに、取得単位数を増やすメソッドを付け加えるにはどうすればいいでしょうか。引数は新たに取得した単位数、返り値は増えた後の単位数とします。
new でインスタンスを作る時に、インスタンス変数の初期値の設定などの準備作業をしたいことがよくあります。そのような時はコンストラクタ(constructor)を使います。コンストラクタ宣言はメソッド宣言とそっくりですが、違う点がいくつかあります。
Nation クラスの変数を設定するコンストラクタを付け加えてみましょう。
こうすると、インスタンス変数に直接代入せず、new の引数で必要なデータを渡すことができます。
前の練習問題の学生クラスに、インスタンス変数の初期値を設定するコンストラクタを付け加えるにはどうすればいいでしょうか。引数は名前、身長、体重の三つで、取得単位数の初期値は0とします。
インスタンス変数の宣言は、クラス宣言の本体の中で、どのメソッド宣言にも入らない場所で行います。それに対して、今まで使ってきた変数はメソッド宣言の中で宣言するので、インスタンス変数ではありません。メソッド宣言の中に変数宣言があるような変数をローカル変数(local variable)と呼びます。インスタンス変数、ローカル変数、仮引数の違いは次の通りです。
7.6 練習問題
7.7 コンストラクタ
class Nation {
String name;
int population;
int gdp;
Nation (String n, int p, int g) {
name = n;
population = p;
gdp = g;
}
double gdpPerPerson () {
return (double)gdp / (double)population;
}
}
Nation x = new Nation("United Kingdom", 58201, 1102658);
int a = x.gdpPerPerson();
7.8 練習問題
7.9 変数の種類
インスタンス変数 | ローカル変数 | 仮引数 | |
---|---|---|---|
宣言の場所 | クラス宣言の中でメソッド宣言の外 | メソッド宣言の中 | メソッド名の直後の括弧の中 |
使える範囲 | プログラム全体(注1) | 変数宣言を含む最も内側のブロックだけ(注2) | そのメソッドだけ |
初期値 | インスタンスが作られた時に初期値が代入される | 変数宣言が実行されるときに初期値が代入される | メソッド呼び出しの時に実引数が代入される |
存続期間 | ずっと存在する | ブロックの実行が終了すると消えてしまう(注2) | メソッドの実行が終了すると消えてしまう |
(注1)他のインスタンスで使うときは、「インスタンス」+「ピリオド」を前に付けなければなりません。
(注2)for の直後の括弧の中で宣言された変数は、使える範囲がその for 文全体で、存続期間はその for 文が終了するまでです。
それでは、実際にクラスを書いてみましょう。画面上でボールを少しずつずらしながら描いていって、動いているように見せるのが目標です。ボールは一つだけとは限らないので、ボールの現在位置や速度を記憶しておくインスタンスをたくさん作れるようにします。
図形を動かすプログラムの土台が用意してありますので、まずこれを自分の作業ディレクトリにコピーしてください。
7.10 ボールを動かす
本文の説明は CNS の場合です。ラップトップの場合は /pub/sfc/ipl/1bc からのコピーは
|
% cd /pub/sfc/ipl/1bc % cp SfcTemplate3.java SfcTemplate3.html 自分の作業ディレクトリ % |
% cd 自分の作業ディレクトリ % cp SfcTemplate3.java MovingBall.java % cp SfcTemplate3.html MovingBall.html % |
プログラム名の変更は、今までと同じ要領です。
MovingBall.java
9 10 |
public class MovingBall extends Applet implements ActionListener, MouseListener, MouseMotionListener, Runnable { |
MovingBall.html
8 |
<applet code="MovingBall.class" width=400 height=380> |
93 |
// ここに自分で作ったクラスを書く。
|
12 |
// ここで自分の作ったインスタンスを覚えておく変数を宣言する。
|
37 |
// ここでインスタンスを作り、変数に記憶させる。
|
18 |
// ここで描画領域に図形を描く。(0.2秒間隔で呼び出される)
|
上のプログラムは、0.2秒間隔で draw を呼び出しているのですが、x, y の値が変わらないので、同じ位置に円を描き続けます。呼び出されるたびに x, y の値を少しずつ変えてやると、円を描く位置がずれるので、動いているように見えます。
上のプログラムでは、描画領域の右端まで行ってもボールが動き続けるので、見えなくなってしまいます。右端まで行ったら跳ね返って、左方向に動くようにしましょう。
右端だけでなく、左、上、下(Y 座標が300)でも跳ね返るようにしなさい。また、ボールの数を増やして、いろいろな色と速度のボールが動くようにしなさい。
実行例
StringTokenizer クラスを使うと、文字列をコンマなどの区切りで分解して取り出すことができます。使い方は次の通りです。
7.15 おまけ
これを使って、X 座標、Y 座標、半径を入力し、その位置に円を描くプログラムを作りなさい。(土台は SfcTemplate2 です)
import java.util.StringTokenizer;
を書きます。これは、別のところで宣言してあるクラスを使うという印です。
new StringTokenizer(String s, String separator);
s は分解したい文字列、separator は区切り文字です。例えば、"100,200,40" という文字列をコンマで区切って分解したいときは、
StringTokenizer st = new StringTokenizer("100,200,40", ",");
とします。
String nextToken()
上の例では、最初に st.nextToken() を実行すると、"100" が、2回目に実行すると "200" が、3回目に実行すると "40" が返ってきます。
[目次]
[前回]
[次回]
[重要語索引]
慶應義塾大学の授業以外での無断利用、複製はご遠慮下さい。
Copyright (c) 2000 慶應義塾大学