Javaは、 オブジェクト指向言語 ( object-oriented language ) に分類されます。 つまり、Java言語では、 オブジェクト指向プログラミング ( object-oriented programming ) を行うということです。 この「オブジェクト指向」とは、プログラミング・パラダイムの一種です。 プログラミング・パラダイム ( programming paradigm )とは、プログラミングの基礎となる考え方のことです。 まとめますと、Javaは「オブジェクト指向」という考え方に基づいてプログラミングを行う言語です。
では、オブジェクトとは何でしょうか。 一言で言えば、 オブジェクト ( object ) とはある種の構造を持つデータです。 レコード(C言語では構造体)も構造を持つデータですが、レコードが変数のかたまりなのに対して、オブジェクトは変数と関数・手続きのかたまりです。
世界の物理的存在や概念的存在をコンピュータで処理する場合、処理の対象を写し取る、つまりモデル化する必要があります。 このとき、対象の性質を変数に対応させ、対象の機能を関数・手続きに対応させますと、比較的素直にモデル化できます。 処理の対象ごとに、関連性のある変数と関数・手続きをまとめたものがオブジェクトなのです。
例として、物理的存在である電灯を取り上げます。 電灯についてコンピュータ処理を行うには、まず、電灯のモデルを考えます。 ここでは、電灯とは、ひもを引くと電気が入って部屋が明るくなり、もう一度ひもを引くと電気が切れて部屋が暗くなるものとします。 電気が入ることは、電灯の性質です。 ひもが引けることは、電灯の機能です。 結果的に部屋を明るくすることも、電灯の機能です。 したがって、電灯を表すオブジェクトは、
をまとめたものとなります。
もう一つの例は、概念的存在である正方形についてです。 正方形をモデル化して、辺の長さを決めると面積が決まるものとします。 辺の長さは、正方形の性質です。 辺の長さが決められることは、正方形の機能です。 結果的に面積が決まることも、正方形の機能です。 したがって、正方形を表すオブジェクトは、
をまとめたものになります。
Javaでは、オブジェクトの中の変数を インスタンス変数 ( instance variable ) とよび、オブジェクトの中の関数と手続きを インスタンス・メソッド ( instance method ) とよびます。
世界 | モデル | Java |
---|---|---|
対象 | オブジェクト | オブジェクト |
性質 | 変数 | インスタンス変数 |
機能 | 関数、手続き | インスタンス・メソッド |
オブジェクトが変数と関数・手続きのかたまりであることは分かりました。 では、この関数や手続きは、どうしたら呼び出せるでしょうか。
オブジェクト指向プログラミングでは、オブジェクトは互いに メッセージ ( message ) を送りあって相互に作用していると考えます。 そして、オブジェクトがメッセージを受け取りますと、それに応じてオブジェクトの中の関数や手続きが呼び出されるのです。 メッセージ自体は単なる記号列ですが、より詳しい情報を送るために引数を持つ場合もあります。
電灯の例では、ひもを引くことを"pullString"というメッセージで表すことにします。 すると、電灯のひもを引くことは、電灯を表すオブジェクトにメッセージ"pullString"を送ることになります。
正方形の例では、面積を求めることを"getArea"というメッセージで表すことにします。 すると、正方形の面積を求めることは、正方形を表すオブジェクトにメッセージ"getArea"を送ることになります。
Javaでは、インスタンス・メソッドの名前がメッセージになります。 オブジェクトとメッセージをドット(.)で結びますと、そのオブジェクトにそのメッセージを送ることになります。
電灯の例では、電灯オブジェクト lamp にメッセージ"pullString"を送ることは、Javaでは文 lamp . pullString () を実行することになります。 括弧の中は引数を表しますが、引数がないので、開いた括弧をすぐに閉じています。
正方形の例では、正方形オブジェクト square にメッセージ"getArea"を送ることは、Javaでは式 square . getArea () を計算することになります。
オブジェクトという言葉は、しばしば混乱を招きます。 データの型を意味することもありますし、データ自身を意味することもあります。
オブジェクト指向プログラミングでは、データ型としてのオブジェクトをクラスとよび、データ自身としてのオブジェクトをインスタンスとよびます。 つまり、クラスはインスタンスの集まりであり、インスタンスはあるクラスに属します。
Javaでも、クラスとインスタンスという単語をこの意味で用います。
電灯の例では、電灯オブジェクトのデータ型を、クラス
Lamp
とします。
すると、電灯オブジェクトは、クラス
Lamp
のインスタンスとなります。
インスタンス
lamp
を生成するには、文
lamp
=
new
Lamp
() を実行します。
正方形の例では、正方形オブジェクトのデータ型を、クラス
Square
とします。
すると、正方形オブジェクトは、クラス
Square
のインスタンスとなります。
インスタンス
square
を生成するには、文
square
=
new
Square
() を実行します。
それでは、実際にプログラムを作成します。 クラスの定義と実行プログラムは分離したほうが分かりやすいので、ここではそのようにします。
まず、電灯のクラス定義についてです。
電気が入っているかどうかを表すインスタンス変数を isCharged とします。 ひもを引くというインスタンス・メソッドを pullString とします。 部屋の明るさを求めるインスタンス・メソッドを getLightness とします。
インスタンス変数
isCharged
は論理型とします。
電気が入っていれば
true
という値を持ち、切れていれば
false
という値を持ちます。
プログラムでは、インスタンスを表すキーワード
this
に注意してください。
また、インスタンス・メソッド
getLightness
は、部屋の明るさとして100%か0%を返します。
/* 1*/ class Lamp { /* 2*/ boolean isCharged = false; /* 3*/ void pullString () { /* 4*/ if (this.isCharged) { /* 5*/ this.isCharged = false; /* 6*/ } else { /* 7*/ this.isCharged = true; /* 8*/ } /* 9*/ } /* 10*/ int getLightness () { /* 11*/ if (this.isCharged) { /* 12*/ return 100; /* 13*/ } else { /* 14*/ return 0; /* 15*/ } /* 16*/ } /* 17*/ }
次に、実行プログラムについてです。
ある時、部屋の明るさは0%でした。 ひもを引いたら、部屋の明るさは100%になりました。 もう一度ひもを引いたら、部屋の明るさは0%になりました。 以下のプログラムは、このことを実現しています。
/* 1*/ class LampMain { /* 2*/ public static void main (String[] args) { /* 3*/ Lamp lamp = new Lamp(); /* 4*/ System.out.println(lamp.getLightness()); /* 5*/ lamp.pullString(); /* 6*/ System.out.println(lamp.getLightness()); /* 7*/ lamp.pullString(); /* 8*/ System.out.println(lamp.getLightness()); /* 9*/ } /* 10*/ }
b04a001@AsiaA1:~/comp3b% java LampMain 0 100 0 b04a001@AsiaA1:~/comp3b%
続いて、正方形のクラス定義についてです。
辺の長さを表すインスタンス変数を size とします。 辺の長さを決めるインスタンス・メソッドを setSize とします。 面積を求めるインスタンス・メソッドを getArea とします。
インスタンス・メソッド
setSize
には引数が1つあることに注意してください。
代入文の
this
.
size
の方がインスタンス変数で、
size
の方が仮引数です。
/* 1*/ class Square { /* 2*/ int size = 0; /* 3*/ void setSize (int size) { /* 4*/ this.size = size; /* 5*/ } /* 6*/ int getArea () { /* 7*/ return this.size * this.size; /* 8*/ } /* 9*/ }
最後に、実行プログラムについてです。
ある時、正方形の辺の長さを5にしましたら、面積は25になりました。 正方形の辺の長さを10にしましたら、面積は100になりました。 以下のプログラムは、このことを実現しています。
/* 1*/ class SquareMain { /* 2*/ public static void main (String[] args) { /* 3*/ Square square = new Square(); /* 4*/ square.setSize(5); /* 5*/ System.out.println(square.getArea()); /* 6*/ square.setSize(10); /* 7*/ System.out.println(square.getArea()); /* 8*/ } /* 9*/ }
b04a001@AsiaA1:~/comp3b% java SquareMain 25 100 b04a001@AsiaA1:~/comp3b%
二球式の電灯について、プログラムを作成してください。
二球式の電灯とは、大きな電球と小さな電球が一緒になっている電灯です。 ひもを引きますと、大きな方に電気が入り、部屋が明るくなります。 もう一度ひもを引きますと、小さな方に電気が入り、部屋が少しだけ明るくなります。 さらにもう一度ひもを引きますと、電気が切れて、部屋が暗くなります。
ある時、部屋の明るさは0%でした。 ひもを引いたら、部屋の明るさは100%になりました。 もう一度ひもを引いたら、部屋の明るさは10%になりました。 最後にひもを引いたら、部屋の明るさは0%になりました。 このことを、プログラムを作成して実現してください。
ここで、二球式電灯のクラスの名前を DoubleLamp とします。 ひもを引くというインスタンス・メソッドは pullString です。 明るさを求めるというインスタンス・メソッドは getLightness です。 実行プログラムは以下の通りとし、クラス DoubleLamp の定義プログラムを作成してください。
プログラミングの方針はいくつか考えられますが、大きな電球のためのインスタンス変数 isChargedToBig と、小さな電球のためのインスタンス変数 isChargedToSmall を用意しますと、うまくいきます。 ひもを引いた時、大きな方に電気が入っていれば、大きな方の電気が切れ、小さな方に電気が入ります。 小さな方に電気が入っていれば、小さな方の電気が切れます。 どちらでもなければ、両方の電気が切れていますので、大きな方に電気が入ります。 部屋の明るさは、大きな方に電気が入っていれば100%, 小さな方に電気が入っていれば10%です。 どちらでもなければ、両方の電気が切れていますので、0%です。
/* 1*/ class DoubleLampMain { /* 2*/ public static void main (String[] args) { /* 3*/ DoubleLamp lamp = new DoubleLamp(); /* 4*/ System.out.println(lamp.getLightness()); /* 5*/ lamp.pullString(); /* 6*/ System.out.println(lamp.getLightness()); /* 7*/ lamp.pullString(); /* 8*/ System.out.println(lamp.getLightness()); /* 9*/ lamp.pullString(); /* 10*/ System.out.println(lamp.getLightness()); /* 11*/ } /* 12*/ }
b04a001@AsiaA1:~/comp3b% java DoubleLampMain 0 100 10 0 b04a001@AsiaA1:~/comp3b%
今日の演習9の答案(Javaプログラム)をメールで提出してください。 メールの差出人は学内のアドレス(b04a001@twcu.ac.jpなど)とし、メールの宛先はkonishi@twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(12月2日)を明記してください。