インスタンスメソッド

上のように,多くのメソッドはあるクラスと深い関連を持っている.そのた め,クラスメソッドの第1引数を略したような使い方をするインスタンス メソッドが用意 されている.なお, 単に「メソッド」と書いた場合はインスタンスメソッドをさす

インスタンスメソッドの宣言はクラス内部で,

返り値の型 メソッド名(引数宣言){
  メソッド本体
}
とする.呼び出し側は「式.メソッド名(引数1, 引数2, ... , 引数n)」のよう に書く.「式」の部分は呼び出すメソッドを含むクラスの型の式であれば 何でも良いが,その型の変数であることが多い.

メソッド本体では,クラスメソッドでの第1引数にあたる呼び出し側の「式」の 部分を受け取るのは,thisという宣言不要の変数である.

インスタンスメソッド呼び出しの例を見てみよう.

class Point2D {
  double x,y;
    // staticをつけないとインスタンスメソッドとなる。
    // 2点間の距離を返すメソッドだが、1つの点は変数 thisに渡されるので
    // 引数は1つで良い。
  double distance2D(Point2D point2){
    double dx=(this.x-point2.x),dy=(this.y-point2.y);
    return Math.sqrt(dx*dx+dy*dy);
  }
    // (0,0)との距離(ベクトルとしての長さ)を求めるインスタンスメソッド
    // 引数はいらない。
  double length(){
    return Math.sqrt(this.x*this.x+this.y*this.y);
  }
}

class ObjectTest4 {
  public static void main(String[] args){
    Point2D p1,p2,p3;
    p1=new Point2D();
    p1.x=0.0; 
    p1.y=0.0;
    p2=new Point2D();
    p2.x=1.0; 
    p2.y=1.0;
    p3=new Point2D();
    p3.x=0.0; 
    p3.y=1.0;
      // インスタンスメソッドは「式.メソッド名」のように呼び出す。
      // 式がどのクラスのオブジェクトかによってインスタンスに実行するメソッドが決まる
    System.out.println("length of p1 = "+p1.length());
    System.out.println("length of p2 = "+p2.length());
    System.out.println("length of p3 = "+p3.length());
    System.out.println("distance between p1 and p2 "+p1.distance2D(p2));
    System.out.println("distance between p2 and p3 "+p2.distance2D(p3));
    System.out.println("distance between p3 and p1 "+p3.distance2D(p1));
  }
}
上の例ではインスタンスメソッドの中で同じクラスのインスタンス変数 x のことを, this.x と書いたが,略記法として x とだけ書くことも許される.今回は説明 のため,"this." をつけたが通常のプログラムではつけないのが普通である.

基本クラスのインスタンスメソッドの例

これまで出てきた,システムの基本クラス Stringクラス のインスタンスメソッドの例を見る. equals(Object)というメソッドは
class StTest1{
  public static void main(String[] args){
    if(args[0].equals("tanaka")){
      System.out.println("あなたはおそらく田中さんですね(棚香かも).");
    }
    else{
      System.out.println("あなたは田中さんですはありませんね");
    }
  }
}
のように,String型のインスタンス(この場合は args[0]の中に入っている文字列) に関連づけられているのでインスタンスメソッドになる.
説明の都合上クラスメソッドの方を先に説明したが,実際のプログラムで使わ れるのはインスタンスメソッドの方が多い(というか,オブジェクト指向言語に適した プログラム設計を行うと必然的にそうなる).クラスメソッドが使われるのは, 以下のような場合などである.
  • 基本データ型などオブジェクト型でないものを引数とする場合.

    たとえば,以前出てきた int型の変数 x を文字列にする際に, Integer.parseInt(x) とクラスメソッドを呼び出したが,int型がオブジェクト型 だったとしたら,parseIntをクラスintのインスタンスメソッドにして x.parseInt() と 書けるようにするだろう.

  • public static void main(String[])

    プログラムをスタートする際の main メソッドはクラスメソッドになっている.

ここまでの説明では,インスタンスメソッドを導入することによるメリットとしては, 呼び出し側のプログラムが簡単に書けるという以上のことは分かっていないが, 後でやる継承(inheritance)によって,インスタンスメソッドはクラスメソッドとは質的 に違った能力を持つ.
クラス内の変数の宣言に static をつけると,クラス変数といって,そのク ラスのインスタンスを作らずに参照できる変数ができる.

これまでには, Math.PIなどが出てきた.しかし,通常のプログラミングではそれほど問題に ならない.

データフィールドへのアクセスを直接書くのではなく,参照(get)する場合と, 設定(set)する場合に分けてインスタンスメソッドにするのが良いと言う考え 方もある.さきほどのPoint2Dの例では,データフィールドx,yへのアクセス のために,
class Point2D {
  private double x,y;
  double getX(){
    return x;
  }
  void setX(double val){
    x=val;
  }
  double getY(){
    return y;
  }
  void setY(double val){
    y=val;
  }
  ...
}
のように,getter, setterとよばれるメソッドを定義するのである.更に, データフィールドの宣言のところに,「private」というキーワードをつけ ているが,これによりクラス外からのデータフィールドの直接アクセスを禁 じている.そのため,Point2Dクラス以外のメソッド中に
	Point2D p1=new Point2D(0,3);
	p1.x=1;
のようなコードを書くと,コンパイル時に,
tt.java:26: x は Point2D で private アクセスされます。
	p1.x=1;
          ^
エラー 1 個
のようなエラーが出てしまう.
次へ進む