オブジェクト指向へ向けて

<概要>クラスの基礎を学びます。前半の終わりであり、後半の始まりであ〜る。

例題10-1 クラスの宣言・代入・参照。

○プログラム

//Kamoku.java

public class Kamoku{
  String namae;
  int tensuu;
  public String mojiretsu(){
    return namae+"は"+tensuu+"点";
  }
  public String toString(){
    return namae+"は"+tensuu+"点";
  }
}


//KamokuTest.java

public class KamokuTest{
  public static void main(String[] args){
    Kamoku kamoku=new Kamoku();

    kamoku.namae="国語";
    kamoku.tensuu=63;

    System.out.println(kamoku.mojiretsu());
    System.out.println(kamoku);
  }
}


○実行結果

D:\atsushi\Java\p240>java KamokuTest
国語は63点
国語は63点
-- Press any key to exit (Input "c" to continue) --

○注意

public なクラス Kamoku と KamokuTest は別々のソースファイルに書かなければなりません。
二つのソースファイルは同じフォルダに置いておくのが無難です。
また、実行したい場合は、両方ともコンパイルした後に、
KamokuTest の方をコマンドラインで指定しましょう。

○解説

//Kamoku.java

1. public class Kamoku{

public はアクセス制御キーワードの一つで、「誰でも使える」ことを表しています。
詳しくは「パッケージ」で解説します。

2. String namae;
3. int tensuu;

これらはフィールドです。
詳しくは例題10-2を参照して下さい。

4. public String mojiretsu(){

static が無いことに注目して下さい。
詳しくは後述します。

mojiretsu メソッドの処理内容
 return namae+"は"+tensuu+"点";
は、次のように書くことも出来ます。
 return toString();

7. public String toString(){

toString メソッドは特別なメソッドです。
文字列連結の演算子 + によってインスタンス(クラスの実体)を文字列に変換するとき、
そのインスタンスの toString メソッドを自動的に呼び出します。
また、System.out.println() や System.out.print() にインスタンスを渡すと、
自動的にそのインスタンスの toString() を使って文字列に変換してから表示してくれます。
つまり、文字列と見なせるときはそのインスタンスの toString メソッドを自動的に呼び出してくれるのです。
「クラスの」ではなく「インスタンスの」です。
インスタンスごとにフィールドの値などは異なりますよね。

//KamokuTest.java

3. Kamoku kamoku=new Kamoku();

クラス宣言の基本的な書き方です。
クラスの名前の後の括弧 () が謎だと思うのですが、
これはデフォルトコンストラクタを呼び出しています。
C++言語の場合は括弧 () を省略した……と言うか、
明示的にコンストラクタを呼び出さなかった場合にデフォルトコンストラクタが呼び出されましたが、
さすがJava言語はチェックが厳しいですねー(汗)。
自分でデフォルトコンストラクタを呼び出さなければならないんですから。

クラスの実体のことをインスタンスと言います。
クラス型の変数のことではありません。
この違いは非常に重要です!
インスタンスとは、プログラムの上からは見えないけれど、
メモリ領域として存在するデータの集まりのことです。

オブジェクトと言うこともあります。
抽象的なものであるクラスが、具体的なものとなることから、この名前が付けられました。
インスタンス( instance )とは、英語で「実例」という意味です。
本問の場合も、科目情報を表すクラスが、国語の科目情報を表すインスタントとなりました。

9. System.out.println(kamoku);

インスタンスを渡すだけで、toString メソッドを自動的に呼び出してくれます。

インスタンスメソッドとクラスメソッド

static キーワードが付いているメソッドはクラスメソッド、あるいは static メソッドと言います。
クラスメソッドは、インスタンスを作らなくても呼び出せるメソッドです。
main メソッドやこれまで作ってきたメソッドはすべてクラスメソッドでした。

static キーワードが付いていないメソッドはインスタンスメソッド、あるいは非 static メソッドと言います。
クラスメソッドと違い、宣言されているクラス外部から
インスタンスメソッドを呼び出す為にはインスタンスを通す必要があります。
しかし、同じクラスのインスタンスメソッド同士ならばお互いを呼び出すことが可能です。


ちょっと分かり難いですが、本質を掴めば、
例えば、同じクラスであってもクラスメソッド内部からインスタンスメソッドを直接呼び出すことが出来ないこと、
そしてその理由は容易に想像がつきます。
何故って?
クラスメソッドはクラス外部からも直接呼べちゃうのに、
その内部でインスタンスメソッドを呼んじゃマズイでしょ?
インスタンスメソッドはインスタンスを通さなきゃいけないのに。

○補足

フィールドにも、クラスフィールド、インスタンスフィールドというのがあります。
詳しくは「クラスとインスタンス」で解説します。

例題10-2 変数とフィールドの違い。

○プログラム

//Field.java

public class Field{
  int a;
  public Field(int a,int b,int c){
    this.a=a;
    this.b=b;
    this.c=c;
  }
  int b;
  public String toString(){
    return "a="+a+" b="+b+" c="+c;
  }
  int c;
}


//FieldTest.java

public class FieldTest{
  public static void main(String[] args){
    Field field=new Field(1,2,3);
    System.out.println(field);
  }
}


○実行結果

D:\atsushi\Java\p254>java FieldTest
a=1 b=2 c=3
-- Press any key to exit (Input "c" to continue) --

○解説

Field クラスとして宣言した field はフィールドでしょうか?変数でしょうか?
答えは変数です。
フィールドは、そのクラスのどのメソッドからでも使えますが、
変数は、宣言されているメソッドの中でしか使えません。

メソッドの仮引数ではない a,b,c はフィールドです。

this は現在のインスタンスを表します。
this はフィールドと変数、仮引数が区別できないときに使います。
必ず使わなければいけないものではありません。
また、this はインスタンスメソッドの中でしか使うことが出来ません。
何故ならば、クラスメソッドはインスタンスを作成することなく呼び出すからです。

○補足

フィールドと変数は別物です。
したがって、フィールドと変数で同じ型、同じ名前のモノを作ることが出来ます。

例題10-3 クラス型配列を用いたプログラムを作って下さい。

○プログラム

//Kamoku.java

public class Kamoku{
  String namae;
  int tensuu;
  public Kamoku(String namae,int tensuu){
    this.namae=namae;
    this.tensuu=tensuu;
  }
  public String toString(){
    return namae+"は"+tensuu+"点";
  }
}


//KamokuHeikin.java

public class KamokuHeikin{
  public static void main(String[] args){
    Kamoku[] kamoku={
      new Kamoku("国語",63),
      new Kamoku("数学",90),
      new Kamoku("英語",75),
      new Kamoku("理科",45),
      new Kamoku("社会",81),
    };
    int sum=0;
    for(int i=0;i<kamoku.length;i++){
      System.out.println(kamoku[i]);
      sum+=kamoku[i].tensuu;
    }
    double heikin=(double)sum/kamoku.length;
    System.out.println("平均点は"+heikin+"点");
  }
}


○実行結果

D:\atsushi\Java\List10-3&4>java KamokuHeikin
国語は63点
数学は90点
英語は75点
理科は45点
社会は81点
平均点は70.8点
-- Press any key to exit (Input "c" to continue) --

○解説

//Kamoku.java

4. public Kamoku(String namae,int tensuu){

Kamoku はコンストラクタです。
コンストラクタにはいくつか決まりがあります。
・コンストラクタの名前はクラスの名前と同じ。
・コンストラクタの戻り値はない( void 型でもない)。


//KamokuHeikin.java

3. Kamoku[] kamoku={
4.  new Kamoku("国語",63),
5.  new Kamoku("数学",90),
6.  new Kamoku("英語",75),
7.  new Kamoku("理科",45),
8.  new Kamoku("社会",81),
9. };

Kamoku 型配列を作っています。
コンストラクタの使い方はC++言語と一緒ですね。
ちょっと分かり難いプログラムになっていますが、
分解すれば次と全く同じです。

Kamoku[] kamoku=new Kamoku[5];
kamoku[0]=new Kamoku("国語",63);
kamoku[1]=new Kamoku("数学",90);
kamoku[2]=new Kamoku("英語",75);
kamoku[3]=new Kamoku("理科",45);
kamoku[4]=new Kamoku("社会",81);


○補足

コンストラクタがある場合は、必ず使わなければなりません。
デフォルトコンストラクタは使えません。
これはC++言語でも同じでしたね。
コンストラクタは強く使うことを推奨されていますが、
宣言と同時に初期化しなければならないという欠点があるため、
敢えてコンストラクタは作らない、というのもアリです。

例題10-4 コンストラクタの多重定義。

○プログラム

長いので別窓でご用意致しました( ClickHere )。
全然難しくないのでご安心を。

○実行結果

D:\atsushi\Java\ListA10-2&3>java StudentTest
[結城浩,65,90,100] -> 255
[阿部和馬,82,73,64] -> 219
[伊藤光一,74,31,42] -> 147
[佐藤太郎,100,95,99] -> 294
-- Press any key to exit (Input "c" to continue) --

○解説

コンストラクタを多重定義しています。
それだけです(笑)。

tens=new int[]{x,y,z};

は、次と全く同じです。

tens=new int[3];
tens[0]=x;
tens[1]=y;
tens[2]=z;


例題10-5 クラスを返却値型とするメソッド。

○プログラム

class MyojiNamae{
  String myoji;
  String namae;
}

public class MethodTest4{
  public static MyojiNamae getYourName(){
    MyojiNamae obj=new MyojiNamae();
    obj.myoji="福沢";
    obj.namae="諭吉";
    return obj;
  }
  public static void main(String[] args){
    MyojiNamae mn=getYourName();
    System.out.println("名字は"+mn.myoji);
    System.out.println("名前は"+mn.namae);
  }
}


○実行結果

D:\atsushi\Java\ListA8-5>java MethodTest4
名字は福沢
名前は諭吉
-- Press any key to exit (Input "c" to continue) --

○解説

1. class MyojiNamae{

public が付いていないことに注目して下さい。
public でないクラスは同じソースファイルの中で宣言できます。

14. MyojiNamae mn=getYourName();

new していないことに注目して下さい。
mn に代入されたのは obj へのポインタです。
クラスは参照型ですからね。


戻る / ホーム