Java super クラス継承の際のコンストラクタについて

派生クラスでは、
基本クラスのメンバの初期化については気にする必要がありません。

その理由としては、派生クラスのコンストラクタ内では、
自動的に基本クラスのコンストラクタが呼び出される
ようになっているからです。

また、基本クラスのコンストラクタ呼び出し処理を
手動で記述する事も可能です。

/********** 基本クラス **********/
class kihon {

      public int data1;

      public kihon() {
            data1 = 1;
      }
}

/********** 派生クラス **********/
class hasei extends kihon {

      public int data2;

      public hasei() {
            data2 = 2;
      }
}

public class Cmain {

      public static void main(String[] args) {

            hasei obj = new hasei();

            System.out.printf("data1 = %d\n", obj.data1);
            System.out.printf("data2 = %d\n", obj.data2);

      }
}

このプログラムでは、
基本クラスにメンバ変数が1つ、派生クラスにもメンバ変数が
1つ用意されています。
そして、派生クラスのインスタンスを作成しています。

この時には、当然、派生クラスのコンストラクタが呼ばれます。

そして、このプログラムを実行すると、

data1 = 1
data2 = 2

と表示されます。

基本クラスのメンバ変数data1に1を設定した覚えはありません。

しかし、基本クラスのメンバ変数data1には1が設定されています。

これは基本クラスのコンストラクタが自動実行された
という事が言えます。

どこで実行されているのかと言うと、
派生クラスのコンストラクタの先頭行です。

つまり、内部では、
派生クラスのコンストラクタ内の記述は次のようになっています。

public hasei() {
     super();
     data2 = 2;
}

ここで、super();と言う記述が出てきましたが、

このsuperと言うキーワードは、
基本クラスの参照を表す特殊なキーワードです。

つまり、super();と言う記述は、
基本クラスのコンストラクタ呼び出しコードです。

この記述はプログラマが記述しなくても自動的に追加されます。

常に自動的に追加されるのは、super();と言う記述です。

これは、基本クラスの引数なしタイプのコンストラクタ呼び出しです。

引数ありタイプの基本クラスのコンストラクタ呼び出しコードは
自動では追加されません。


明示的に基本クラスのコンストラクタを呼び出す場合

上記の例では、
派生クラスのコンストラクタ内に
基本クラスのコンストラクタ呼び出しコードが
自動的に追加されましたが、
手動でプログラマが記述する事もできます

手動で記述する事により、
基本クラスの引数ありタイプのコンストラクタ
呼び出しも可能になります。

手動で記述する場合の注意点として、
派生クラスのコンストラクタ内の先頭行に記述する必要があります。

/********** 基本クラス **********/
class kihon {

      public int data1;

      public kihon() {
            data1 = 1;
      }
}

/********** 派生クラス **********/
class hasei extends kihon {

      public int data2;

      public hasei() {
            super();
            data2 = 2;
      }
}

public class Cmain {

      public static void main(String[] args) {

            hasei obj = new hasei();

            System.out.printf("data1 = %d\n", obj.data1);
            System.out.printf("data2 = %d\n", obj.data2);

      }
}

派生クラスのコンストラクタ内に、
super();を手動で追加した例です。

下記のように、
super();を先頭行ではない位置に記述するとエラーとなります。

public hasei() {
      data2 = 2;
      super();      // 先頭行に記述しなくてはならないのでエラー
}

次にsuperを使って、
引数ありタイプの基本クラスのコンストラクタ呼び出しコードを
記述してみます。

/********** 基本クラス **********/
class kihon {

      public int data1;

      public kihon() {
            data1 = 1;
      }

      public kihon(int a) {
            data1 = a;
      }
}

/********** 派生クラス **********/
class hasei extends kihon {

      public int data2;

      public hasei() {
            super();
            data2 = 2;
      }

      public hasei(int a) {
            super(a);
            data2 = 2;
      }

      public hasei(int a, int b) {
            super(a);
            data2 = b;
      }

}

public class Cmain {

      public static void main(String[] args) {

            hasei obj = new hasei();

            System.out.printf("data1=%d\n", obj.data1);
            System.out.printf("data2=%d\n", obj.data2);

            hasei obj2 = new hasei(5);

            System.out.printf("data1=%d\n", obj2.data1);
            System.out.printf("data2=%d\n", obj2.data2);

            hasei obj3 = new hasei(5, 10);

            System.out.printf("data1=%d\n", obj3.data1);
            System.out.printf("data2=%d\n", obj3.data2);

      }
}

このプログラム例では、
派生クラスのコンストラクタ内で、
いろいろな基本クラスのコンストラクタを呼び出しています。

派生クラスの引数なしタイプのコンストラクタ内で記述されている
super();は、前述で説明した通り、省略できます。

ここで、もう一度書きますが、
派生クラスのコンストラクタ内での
基本クラスのコンストラクタ呼び出し処理は、
派生クラスのコンストラクタ内の先頭行に記述する必要があります。