新しい変数の型としてのクラス

新しい変数の型の必要性

配列の練習で Goukei.java をつくりました。たくさんの数値を配列に読み込んでおき、合計を求めるものでした。これがある科目の試験の結果で、生徒の名前も一緒に処理したいという時のことを考えてみます。

既存の変数の型を使った配列

名前の配列を点数の配列と別に作って処理してもよいのですが…

Stringの配列

岩井 亜紀 河合 和子 木原 園子

intの配列

78 45 65

名前と点数を一緒に扱える型を作る

名前と点数が強く結びついたデータなので一緒にあつかえるようにするのがオブジェクト指向らしいやりかたです。

新しい型の変数

岩井 亜紀
78

新しい型の変数の配列

岩井 亜紀 河合 和子 木原 園子
78 45 65

新しい変数の型を定義する

名前(文字列)と点数(整数)の両方をまとめて入れることのできる、新しい変数の型を作ります。

この変数の型に名前をつけて Seito1Kamoku とします。

このような変数の型をjavaではクラスとよびます。class Seito1Kamoku がそれを表しています。

ファイル名 Seito1Kamoku.java

名前の由来は生徒1科目です。

public class Seito1Kamoku { 
    /* フィールド */
    String namae;
    int ten;
    /* コンストラクタ */
    public Seito1Kamoku( String s, int n ){
       namae = s;
       ten   = n;
    }
}

今回のクラスは今までのと異なり、mainの部分がありません。ですからこのまま実行することはできません。新しい変数の型を定義しただけです。

新しい型 Seito1Kamoku には名前と点数をセットで代入することができます。フィールドと書かれている部分でそれを指定しています。

この新しい型の変数は使う時に宣言だけでなく、メモリ上に場所を用意するために new という操作を必要とします。コンストラクタはこの時にしなければならないことを書いておきます。今回のコンストラクタは単に名前と点数に値を代入するものです。

( field:場所,領域 constructor:建造者 )

定義したクラス(新しい型)を使う

次にこれを使うプログラムを書きます。まずは、2人分の名前と点数を代入し、表示してみます。

ファイル名 Seito.java

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 クラスの配列を作る必要があります。

ファイル名 Goukei2.java

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

課題

1.

上記 Seito1Kamoku.java をつくり、コンパイルしなさい。(実行はできません)

ファイル名 Seito1Kamoku.java

2.

上記 Seito.java をつくり、コンパイルしてから実行して結果を確認しなさい。

また seito2.ten = seito2.ten + 10; のようなフィールドの操作を付け加え、点数を変えたり、名前を変えたりしてみなさい。

ファイル名 Seito.java

3.

上記 Goukei2.java をつくり、コンパイルしてから実行して結果を確認しなさい。

ファイル名 Goukei2.java


聖愛高等学校
http://www.seiai.ed.jp/
Last Modified