[目次] [前回] [次回] [重要語索引]

第7週: オブジェクトとは

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 おまけ

7.1 オブジェクト

プログラミング言語にはいろいろな種類がありますが、その中にオブジェクト指向プログラミング言語(object oriented programming language)と呼ばれるものがあり、Java 言語もその一つです。これは、計算の単位としてオブジェクトと呼ばれるものを使います。

オブジェクト(object)とは、いくつかのデータやメソッドをまとめて一塊にしたものです。小さなプログラムを作るときはそれほど便利さを感じませんが、大きなプログラムを作るときは、オブジェクトに分割することによって見通しが良くなるので重要です。

今までのプログラムでも、実はオブジェクトを使っていました。図形を描くときに使う g という変数の中身はオブジェクトです。これを次のような図で表します。

object-1

オブジェクトも、整数や文字列と同じように代入できます。

    h = g;
を実行すると、次の図のようになります。
object-2

7.2 クラス

オブジェクトは、プログラムとしてソースファイルの中に書くものではありません。ソースファイルの中に書くのはクラス(class)です。

例として前回の各国データを考えてみましょう。国名は文字列、人口と GDP は整数なので、一つの配列にすることはできません。三つの配列に分けて記憶しますが、データを修正したり、種類を増やしたりするのが不便です。そこで、一つの国のデータは、一つのオブジェクトにまとめてしまいましょう。

object-3

それぞれのオブジェクトは別のデータを記憶していますが、全く違うデータではなく、「国名(文字列)、人口(整数)、GDP(整数)の三つのデータを持つ」という規則に従っています。この規則を書いたものがクラスで、逆に言えばクラスの規則に従っていれば、他の国のデータをどんどん追加することができます。

「国名(文字列)、人口(整数)、GDP(整数)の三つのデータを持つ」クラスNation をプログラムの形で書くと次のようになります。

    class Nation {
        String name;
	int population;
	int gdp;
    }

これをクラス宣言と呼び、一般には次の形になります。

    class クラス名 {
        クラス本体
    }

クラス名は、変数名やメソッド名と同じ付け方ならば、どんな名前でも構いません。変数名と区別しやすいように、大文字で始めるのが習慣です。

7.3 インスタンス

あるクラスに対して、その規則に従ってデータを記憶しているオブジェクトを、そのクラスのインスタンス(instance)と呼びます。大雑把に言えば、クラスが集合を表していて、インスタンスはその中の具体例です。

インスタンスは、データを覚えておくための変数をいくつか持つことができます。これをインスタンス変数(instance variable)と呼びます。同じクラスのインスタンスは、同じ名前のインスタンス変数を持ちますが、変数が記憶しているデータはインスタンスごとに違います。例えば、クラス Nation のインスタンスは name, population, gdp の三つの変数を持ちます。

インスタンスは、プログラムを実行した結果としてできるものです。クラス Nation のインスタンスを作るには、次の式を実行します。

    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;

7.4 練習問題

  1. 次の表の空欄を埋めなさい。
    クラスインスタンス
    イギリス、エジプト、インド、…
     北海道、東京、京都、沖縄、…
    SFCの学生 
  2. SFCの学生のインスタンスは、名前、取得単位数、身長、体重(小数点以下があります)の四つのデータを記憶するとします。クラス宣言はどのように書けばいいでしょうか。

7.5 メソッド

オブジェクトはデータを記憶するだけでなく、そのデータを使って計算を行うことができます。計算のやり方を指定するのがメソッドです。メソッド宣言は、クラス宣言の中に変数宣言と並べて書きます。

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();

同じインスタンスの中のメソッドを呼び出す時は、「インスタンス」+「ピリオド」を前に付けなくても構いません。前回までのプログラムで、自分で作ったメソッドをメソッド名だけで呼び出していたのは、同じインスタンスの中にあるからです。

7.6 練習問題

前の練習問題で作った学生クラスに、取得単位数を増やすメソッドを付け加えるにはどうすればいいでしょうか。引数は新たに取得した単位数、返り値は増えた後の単位数とします。

7.7 コンストラクタ

new でインスタンスを作る時に、インスタンス変数の初期値の設定などの準備作業をしたいことがよくあります。そのような時はコンストラクタ(constructor)を使います。コンストラクタ宣言はメソッド宣言とそっくりですが、違う点がいくつかあります。

Nation クラスの変数を設定するコンストラクタを付け加えてみましょう。

    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;
	}
    }

こうすると、インスタンス変数に直接代入せず、new の引数で必要なデータを渡すことができます。

    Nation x = new Nation("United Kingdom", 58201, 1102658);
    int a = x.gdpPerPerson();

7.8 練習問題

前の練習問題の学生クラスに、インスタンス変数の初期値を設定するコンストラクタを付け加えるにはどうすればいいでしょうか。引数は名前、身長、体重の三つで、取得単位数の初期値は0とします。

7.9 変数の種類

インスタンス変数の宣言は、クラス宣言の本体の中で、どのメソッド宣言にも入らない場所で行います。それに対して、今まで使ってきた変数はメソッド宣言の中で宣言するので、インスタンス変数ではありません。メソッド宣言の中に変数宣言があるような変数をローカル変数(local variable)と呼びます。インスタンス変数、ローカル変数、仮引数の違いは次の通りです。

インスタンス変数ローカル変数仮引数
宣言の場所クラス宣言の中でメソッド宣言の外メソッド宣言の中メソッド名の直後の括弧の中
使える範囲プログラム全体(注1)変数宣言を含む最も内側のブロックだけ(注2)そのメソッドだけ
初期値インスタンスが作られた時に初期値が代入される変数宣言が実行されるときに初期値が代入されるメソッド呼び出しの時に実引数が代入される
存続期間ずっと存在するブロックの実行が終了すると消えてしまう(注2)メソッドの実行が終了すると消えてしまう

(注1)他のインスタンスで使うときは、「インスタンス」+「ピリオド」を前に付けなければなりません。

(注2)for の直後の括弧の中で宣言された変数は、使える範囲がその for 文全体で、存続期間はその for 文が終了するまでです。

7.10 ボールを動かす

それでは、実際にクラスを書いてみましょう。画面上でボールを少しずつずらしながら描いていって、動いているように見せるのが目標です。ボールは一つだけとは限らないので、ボールの現在位置や速度を記憶しておくインスタンスをたくさん作れるようにします。

図形を動かすプログラムの土台が用意してありますので、まずこれを自分の作業ディレクトリにコピーしてください。
本文の説明は CNS の場合です。ラップトップの場合は /pub/sfc/ipl/1bc からのコピーは FTPによるファイル転送を行ってください。
  1. スタートメニューから[ファイル名を指定して実行(R)]を選択し,表示されたウィンドウの`名前(O)'欄に `ftp' と入力して[OK]を押す。
  2. ftp> open ccz00.sfc.keio.ac.jp
  3. ログイン名とパスワードの入力
  4. ftp> cd /pub/sfc/ipl/1bc
  5. ftp> get SfcTemplate3.java
  6. ftp> get SfcTemplate3.html
  7. ftp> quit
自分の作業ディレクトリにコピーしてから後は同じ手順です。なお、文字コードは iso-2022-jp です。meadow ではそのまま表示できますが、必要ならpage browser などで変換してください。
% cd /pub/sfc/ipl/1bc
% cp SfcTemplate3.java SfcTemplate3.html 自分の作業ディレクトリ
% 
次に MovingBall という名前でプログラムを作る準備をしましょう。
% 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>

7.11 練習問題

手始めに、動かないボールを表示するようにプログラムを書いてみましょう。

7.12 練習問題

上のプログラムは、0.2秒間隔で draw を呼び出しているのですが、x, y の値が変わらないので、同じ位置に円を描き続けます。呼び出されるたびに x, y の値を少しずつ変えてやると、円を描く位置がずれるので、動いているように見えます。

7.13 練習問題

上のプログラムでは、描画領域の右端まで行ってもボールが動き続けるので、見えなくなってしまいます。右端まで行ったら跳ね返って、左方向に動くようにしましょう。

7.14 宿題

右端だけでなく、左、上、下(Y 座標が300)でも跳ね返るようにしなさい。また、ボールの数を増やして、いろいろな色と速度のボールが動くようにしなさい。

実行例

7.15 おまけ

StringTokenizer クラスを使うと、文字列をコンマなどの区切りで分解して取り出すことができます。使い方は次の通りです。

これを使って、X 座標、Y 座標、半径を入力し、その位置に円を描くプログラムを作りなさい。(土台は SfcTemplate2 です)
[目次] [前回] [次回] [重要語索引]

慶應義塾大学の授業以外での無断利用、複製はご遠慮下さい。
Copyright (c) 2000 慶應義塾大学