配列の練習で Goukei.java をつくりました。たくさんの数値を配列に読み込んでおき、合計を求めるものでした。これがある科目の試験の結果で、生徒の名前も一緒に処理したいという時のことを考えてみます。
名前の配列を点数の配列と別に作って処理してもよいのですが…
Stringの配列
岩井 亜紀 | 河合 和子 | 木原 園子 | … |
intの配列
78 | 45 | 65 | … |
名前と点数が強く結びついたデータなので一緒にあつかえるようにするのがオブジェクト指向らしいやりかたです。
新しい型の変数
岩井 亜紀 |
78 |
新しい型の変数の配列
岩井 亜紀 | 河合 和子 | 木原 園子 | … |
78 | 45 | 65 | … |
名前(文字列)と点数(整数)の両方をまとめて入れることのできる、新しい変数の型を作ります。
この変数の型に名前をつけて Seito1Kamoku とします。
このような変数の型をjavaではクラスとよびます。class Seito1Kamoku がそれを表しています。
名前の由来は生徒1科目です。
public class Seito1Kamoku { /* フィールド */ String namae; int ten; /* コンストラクタ */ public Seito1Kamoku( String s, int n ){ namae = s; ten = n; } }
今回のクラスは今までのと異なり、mainの部分がありません。ですからこのまま実行することはできません。新しい変数の型を定義しただけです。
新しい型 Seito1Kamoku には名前と点数をセットで代入することができます。フィールドと書かれている部分でそれを指定しています。
この新しい型の変数は使う時に宣言だけでなく、メモリ上に場所を用意するために new という操作を必要とします。コンストラクタはこの時にしなければならないことを書いておきます。今回のコンストラクタは単に名前と点数に値を代入するものです。
( field:場所,領域 constructor:建造者 )
次にこれを使うプログラムを書きます。まずは、2人分の名前と点数を代入し、表示してみます。
public class Seito { public static void main( String[] args ) { Seito1Kamoku seito1; //宣言 Seito1Kamoku seito2; seito1 = new Seito1Kamoku("岩井 亜紀",78); //インスタンス作成と 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 ); seito2.ten = seito2.ten + 10; //フィールドの参照と代入 System.out.print( seito2.namae ); System.out.print( " " ); System.out.println( seito2.ten ); } }
実行結果は次の通り。
$ java Seito 岩井 亜紀 78 河合 和子 45 河合 和子 55
説明することがたくさんあります。以下に順を追って説明します。
Seito1Kamoku seito1 という部分は Seito1Kamoku という新しい型の変数 seito1 を宣言している部分です。
いままでの変数の型と変数の関係
変数の型 | 変数 |
int | a, b |
新型の変数は値を格納する以外にもいろいろな機能を持たせることができるので「変数の型」といわずに「クラス」。「変数」といわずに「インスタンス」(最近はオブジェクト)といいます。
クラス | インスタンス |
Seito1Kamoku | seito1, seito2 |
カタカナで書くと専門用語のようで難しそうですが、英語では日常的に使う言葉です。次のような意味です。
言葉 | クラス | インスタンス | オブジェクト |
---|---|---|---|
意味 | 分類・種類・なかま・学級 | 例・実例 | もの |
正式には、宣言部分は
int tensuu1; 「 tensuu1 はint型の変数である。」 Seito1Kamoku seito1; 「 seito1 は Seito1Kamokuクラスのインスタンスである。」あるいは、 「 seito1 というオブジェクトは Seito1Kamokuクラスである。」
というのですが、その意味は、
Seito1Kamoku seito1; 「 seito1 は Seito1Kamokuの種類の1例である。」あるいは、 「 seito1 というものは Seito1Kamokuのなかまである。」
となって、従来よりも考えやすい概念になっています。
値の代入について普通のint型の変数と比較します。
普通の変数 tensuu1 = 78; 新型の変数 seito1 = new Seito1Kamoku("岩井 亜紀",78);
変数 tensuu1 では宣言をすれば = 78 とすぐに値を代入することができます。
インスタンス seito1 では、= new Seito1Kamoku("岩井 亜紀",78); のように単純な代入ではありません。new で Seito1Kamoku に必要なフィールドをメモリ上に確保し、コンストラクタに書いてあるように値を代入します。
その結果次のようなインスタンスができます。
seito1 | namae | 岩井 亜紀 |
ten | 78 |
seito2 | namae | 河合 和子 |
ten | 45 |
インスタンスの宣言とメモリの確保,代入を一度に行うこともできます。つぎの2つは全く同じ意味です。
Seito1Kamoku seito1; seito1 = new Seito1Kamoku("岩井 亜紀",78);
Seito1Kamoku seito1 = new Seito1Kamoku("岩井 亜紀",78);
オブジェクト seito1 には、namae と ten の2つのフィールドがあります。(Seito1Kamokuのクラスのインスタンス(オブジェクト)はすべてこうなっています)この2つのフィールドは次のようにすると普通の変数のように取り扱うことができます。
seito1.namae seito1.ten
参照(値を使う)
a = seito1.ten * 10; System.out.println(seito1.namae);
代入
seito1.ten = 100; seito1.namae = "木原 園子";
さて、いよいよ Goukei.java に生徒の名前を合わせて処理をするということに進みます。そのためには Seito1Kamoku クラスの配列を作る必要があります。
public class Goukei2 { 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 ); } }
結果は
$ java Goukei2 岩井 亜紀 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);
上記 Seito1Kamoku.java をつくり、コンパイルしなさい。(実行はできません)
上記 Seito.java をつくり、コンパイルしてから実行して結果を確認しなさい。
また seito2.ten = seito2.ten + 10; のようなフィールドの操作を付け加え、点数を変えたり、名前を変えたりしてみなさい。
上記 Goukei2.java をつくり、コンパイルしてから実行して結果を確認しなさい。