オブジェクト指向とはなにか、オブジェクト指向以前のやり方と比較することでつかんでいきたい。
配列の練習で Goukei.java をつくりました。たくさんの数値を配列に読み込んでおき、合計を求めるものでした。これがある科目の試験の結果で、生徒の名前も一緒に処理したいという時のことを考えてみます。これをクラシックなやり方ではこうなります。(名前は実在の人物ではありません)
public class Goukei2 { public static void main( String[] args ) { String[] namae = {"岩井 亜紀","河合 和子","木原 園子", "布川 麻子","福永 秋絵","三上 美奈", "矢島 千晶","吉沢 裕子","渡辺 智子" }; int[] ten = {78,45,65,35,92,63,57,89,84}; double goukei = 0; for ( int i=0; i < ten.length ; i++ ){ System.out.print( namae[i] ); System.out.print( " " ); System.out.println( ten[i] ); goukei = goukei + ten[i]; } System.out.println( goukei ); System.out.println( goukei/ten.length ); } }
これできちんと処理されますが、プログラムの中では名前と点数が別々の配列に入れられていて、番号で結びつけられています。プログラム言語の都合に合わせてデータの入れ方を工夫しています。
しかし、元のデータは次のような固まりになっているのです。
"岩井 亜紀",78 "河合 和子",45 "木原 園子",65 "布川 麻子",35 ............
プログラムが複雑になり、プログラミングが共同作業になるにつれ、現実のデータを元の形で扱いたいと考えるようになりました。現実のデータの都合に合わせてプログラム言語の仕様を工夫したことになります。これはプログラム言語がオブジェクト指向になった理由のひとつです。
まず、新しい変数の型(実際の名前はクラス)をつくります。
名前の由来は生徒1科目です。
public class Seito1Kamoku { /* フィールド */ String namae; int ten; /* コンストラクタ */ public Seito1Kamoku( String s, int n ){ namae = s; ten = n; } }
今回のクラスは今までのと異なり、mainの部分がありません。ですからこのまま実行することはできません。新しい変数の型を定義しただけです。
新しい型の名前は Seito1Kamoku で、名前と点数をセットで代入することができます。フィールドと描かれている部分でそれを指定しています。
この新しい型の変数は使う時に宣言だけでなく、メモリ上に場所を用意するために new という操作を必要とします。コンストラクタはこの時にしなければならないことを書いておきます。
次にこれを使うプログラムを書きます。まずは、2人分の名前と点数を代入し、表示してみます。
public class Goukei3 { public static void main( String[] args ) { Seito1Kamoku seito1 = new Seito1Kamoku("岩井 亜紀",78); Seito1Kamoku seito2 = new Seito1Kamoku("河合 和子",45); System.out.print( seito1.namae ); System.out.print( " " ); System.out.println( seito1.ten ); System.out.print( seito2.namae ); System.out.print( " " ); System.out.println( seito2.ten ); } }
実行結果は次の通り。
U:\user\java> java Goukei3 岩井 亜紀 78 河合 和子 45
普通のint型の変数と比較します。
普通の変数 int tensuu1 = 78; 新型の変数 Seito1Kamoku seito1 = new Seito1Kamoku("岩井 亜紀",78);
型の名前 変数の名前 = という部分は共通です。ただし、新型の変数は値を代入する以外にもいろいろな機能を持たせることができるので「変数の型」といわずに「クラス」。「変数」といわずに「インスタンス」(最近はオブジェクト)といいます。
カタカナで書くと専門用語のようで難しそうですが、英語では日常的に使う言葉です。次のような意味です。
言葉 | クラス | インスタンス | オブジェクト |
---|---|---|---|
意味 | 分類・種類・なかま・学級 | 例・実例 | もの |
正式には、宣言部分は
int tensuu1; 「 tensuu1 はint型の変数である。」 Seito1Kamoku seito1; 「 seito1 は Seito1Kamokuクラスのインスタンスである。」あるいは、 「 seito1 というオブジェクトは Seito1Kamokuクラスである。」
というのですが、その意味は、
Seito1Kamoku seito1; 「 seito1 は Seito1Kamokuの種類の1例である。」あるいは、 「 seito1 というものは Seito1Kamokuのなかまである。」
となって、従来よりも考えやすい概念になっています。
変数 tensuu1 では = 78 と単に初期値を代入しています。seito1 では、= new Seito1Kamoku("岩井 亜紀",78); のようにしています。オブジェクトには複数のデータが組み合わされていますから単純に代入できません。ここでjavaはSeito1Kamokuに必要な量のメモリを確保し、コンストラクタに従って初期値を代入します。
Seito1Kamokuには、namae と ten の2つのフィールドがある。 コンストラクタは public Seito1Kamoku( String s, int n ) new Seito1Kamoku("岩井 亜紀",78)の部分で、 s が"岩井 亜紀", n が 78 となってコンストラクタが呼ばれる コンストラクタ中の namae = s; ten = n; で、namae と ten の2つのフィールドに、s, n の内容が代入され、オブジェクトができる。
オブジェクト seito1 には、namae と ten の2つのフィールドがある。(Seito1Kamokuのクラスのオブジェクトはすべてこうなっている)この2つのフィールドは次のようにすると普通の変数のように取り扱うことができる。
seito1.namae seito1.ten
オブジェクトを配列に格納し9人の処理をすることにする。
public class Goukei4 { public static void main( String[] args ) { Seito1Kamoku[] test1 = { new Seito1Kamoku("岩井 亜紀",78), new Seito1Kamoku("河合 和子",45), new Seito1Kamoku("木原 園子",65), new Seito1Kamoku("布川 麻子",35), new Seito1Kamoku("福永 秋絵",92), new Seito1Kamoku("三上 美奈",63), new Seito1Kamoku("矢島 千晶",57), new Seito1Kamoku("吉沢 裕子",89), new Seito1Kamoku("渡辺 智子",84) }; double goukei = 0; for ( int i=0; i < test1.length ; i++ ){ System.out.print( test1[i].namae ); System.out.print( " " ); System.out.println( test1[i].ten ); goukei = goukei + test1[i].ten; } System.out.println( goukei ); System.out.println( goukei/test1.length ); } }
結果は
U:\user\java> java Goukei4 岩井 亜紀 78 河合 和子 45 木原 園子 65 布川 麻子 35 福永 秋絵 92 三上 美奈 63 矢島 千晶 57 吉沢 裕子 89 渡辺 智子 84 608.0 67.55555555555556
上記のやり方は、
int[] kazu = {12, 23, 34, 45, 56};
に相当する。大きさだけ決めておいて後で代入する方法もあった。
int[] kazu = new int[5];
この方法でオブジェクトの配列を作る場合は次のようにする。
Seito1Kamoku[] test1 = new Seito1Kamoku[9]; test1[0] = new Seito1Kamoku("岩井 亜紀",78); test1[1] = new Seito1Kamoku("河合 和子",45); test1[2] = new Seito1Kamoku("木原 園子",65); test1[3] = new Seito1Kamoku("布川 麻子",35); test1[4] = new Seito1Kamoku("福永 秋絵",92); test1[5] = new Seito1Kamoku("三上 美奈",63); test1[6] = new Seito1Kamoku("矢島 千晶",57); test1[7] = new Seito1Kamoku("吉沢 裕子",89); test1[8] = new Seito1Kamoku("渡辺 智子",84);