2016年1月15日金曜日

this と super ってなに?

thisとsuperってjavaではよく見かけますが、これってなんでしょうか。まず、thisとsuperには4つの使い道があります。それは、クラスに対してthisもしくはsuperを用いる、コンストラクタに対してthisもしくはsuperを用いる、あるいはクラスのメンバ変数に対してthisもしくはsuperを用いる、メソッドに対してthisもしくはsuperを用いるというものです。

簡単にいえば、「クラスのthis、super」「メンバ変数のthis、super」と「メソッドのthis、super」と「コンストラクタのthis、super」の4種類があるということです。

詳しく見ていきましょう。

メンバ変数のthis、super

まずは「メンバ変数のthis、super」です。コードを見ながら説明します。以下のコード1を見てください。
public class Sample01{
public static void main(String args[]){
SubSample instancedayo1 = new SubSample();
  instancedayo1.powerUp();
System.out.println(" power 1: " + instancedayo1.power);

  SubSample instancedayo2 = new SubSample();
  instancedayo2.powerUp();
  instancedayo2.powerUp();
  instancedayo2.powerUp();
  System.out.println(" power 2: " + instancedayo2.power);
        }
}

class SubSample{
int power = 0;

void powerUp(){
        this.power = this.power + 10;
        }
}
コード1

コード1ではSubSampleクラスからインスタンス「instancedayo1」と「instancedayo2」を作っています。この「instancedayo1」と「instancedayo2」はSubSampleのメソッド「powerUp()」を使っています。このパワーアップメソッドはpowerの値を10だけ上昇させるものです。

「instancedayo1」は1回だけpowerUp()メソッドを使い、「instancedayo2」は3回powerUp()メソッドを使っています。さて、それぞれのインスタンスのpowerはどんな値になっているのでしょうか。コード1を実行してみます。


実行結果

結果がでました。「instancedayo1」のpowerは10、「instancedayo2」のpowerは30です。powerの初期値は0で、「instancedayo1」は1回だけpowerUp()メソッドを使い、「instancedayo2」は3回powerUp()メソッドを使っていたわけですから、それぞれのインスタンスのpowerは10と30になったわけですね。

このように、powerという変数はSubSampleクラスの変数だったわけですが、インスタンスそれぞれで違う振る舞いをしています。すなわち、this.powerと名付けることで、「そのインスタンス固有の変数」に変わったわけです。

(ちなみに、クラス固有の変数、すなわちそれぞれのインスタンスで同じ振る舞いをする変数がほしい場合、staticを変数の前につけ、static変数とします)

なお、変数は基本的にインスタンス固有のものであるとオブジェクト指向のJavaでは考えられるので、this.をつけるのを省略してもインスタンス固有のものとして扱われます。

また、インスタンス固有の変数の場合、コード1のSubSampleクラスの変数は初期化しなくても、インスタンスを作ったときに自動的に初期化されます。

thisの使い方はわかりました。
さて、つぎにsuperのほうです。

superは基本的に、スーパークラスのメンバ変数にアクセスするために使われます。

public class Sample01{
public static void main(String args[]){
            SubSample instancedayo1 = new SubSample();
            instancedayo1.powerUp();
            instancedayo1.defenceUp();
            System.out.println(" power 1: " + instancedayo1.power);
            System.out.println(" defence 1: " + instancedayo1.defence);

            SubSample instancedayo2 = new SubSample();
            instancedayo2.powerUp();
            instancedayo2.powerUp();
            instancedayo2.powerUp();
            instancedayo2.defenceUp();
            instancedayo2.defenceUp();
            System.out.println(" power 2: " + instancedayo2.power);
  System.out.println(" defence 2: " + instancedayo2.defence);
            }
}

class SubSample extends SuperSample{
            int power;

            void powerUp(){
                this.power = this.power + 10;
            }
 
           void defenceUp(){
            super.defence = super.defence + 10;
            }
}

class SuperSample{
            int defence;
}
コード2

実行結果

コード2を見てみましょう。今度はSubSampleクラスがSuperSampleクラスを継承(extends)しています。こうすることによって、SubSampleクラスやそのインスタンスがSuperSampleクラスのメンバ変数やメソッドにアクセスすることができます。

SubSampleクラスがSuperSampleクラスのメンバ変数にアクセスするためにでてくるのが「super」です。SubSampleクラスはdefenceをアップさせる「defenceUp」というメソッドを持っていますが、defence変数はSuperSampleクラス(スーパークラス)の変数です。

SubSampleクラスがスーパークラス(SuperSampleクラス)の変数にアクセスしたいときに「super.defence」と書くことでアクセスが可能になるわけですね。

(とは言いましたが、super.を省略して、単にdefenceとだけ書いてもコンパイルは通ります。ただ、わかりづらいのでsuper.defenceと言うふうに書いたほうがよいでしょう)