Developer

【はじめてのJava】コンストラクタの注意点(呼びなおし時)【クラスの継承編】
2022.02.27
Lv1

【はじめてのJava】コンストラクタの注意点(呼びなおし時)【クラスの継承編】

はじめてのJava

このシリーズでは、初めてJavaやプログラミングを勉強する方向けに、Javaによるプログラミングの基礎を説明していきます。
目標レベルは、Javaの資格試験の一つである「Oracle Certified Java Programmer, Silver」(通称Java Silver)に合格できる程度の知識の習得です。
はじめてJavaやプログラムに触れる方にもできるだけわかりやすい解説を心がけていきます。


クラスの継承編

クラスの継承編では、Javaを扱う上で重要な「クラスの継承」について扱っていきます。

前回は親クラスのコンストラクタの指定方法を扱いました。

今回はsuperを利用したコンストラクタの呼び出し時の注意点を扱います。


目次


thisとsuper

Javaのプログラムを見ているとthissuperといったキーワードを見かけることがあります。

thisについてはこちらの記事の通り、そのインスタンス自身を表すキーワードです。

同様にsuperについてはこちらの記事の通り、親クラスで定義されている要素を示すキーワードです。

 


superによるコンストラクタの呼び出し

前回、子クラスのコンストラクタ内でsuper(引数)とすることで、親クラスのインスタンス部分をインスタンス化する際のコンストラクタを指定することができることを紹介しました。

実はこの呼び出し方には注意点があります。

どういうことか順を追ってみていきましょう。


コンストラクタ呼びなおし時の注意点

コンストラクタを呼びなおす際には コンストラクタ内の最初の処理でコンストラクタの呼びなおしを行う必要があります 

これは「他の処理の後にコンストラクタを呼び出して初期化処理を行うのはおかしい」という点からだと思われます。

例えば以下のコードはコンパイルエラーです。

class ErrorSample{
  //コンストラクタ1
  ErrorSample(){
    System.out.println(); //☆
    this(2); //コンストラクタ2を呼び出しているが・・・★
  }
  //コンストラクタ2
  ErrorSample(int num){
    System.out.println(num);
  }
}

このソースコードは、★の部分でコンストラクタ2を呼びなおしていますが、 その前に☆の処理があるためコンパイルエラーとなります 

☆と★が逆であれば問題なくコンパイル可能です。

class NonErrorSample{
  //コンストラクタ1
  NonErrorSample(){
    this(2); //コンストラクタ2を呼び出している★
    System.out.println(); //☆
  }
  //コンストラクタ2
  NonErrorSample(int num){
    System.out.println(num);
  }
}

こちらは、コンストラクタの最初の処理で別のコンストラクタを呼び出しているのでコンパイルエラーになりません。

この「別のコンストラクタを呼びなおす場合はコンストラクタの最初の処理で行う」というルールは、superを使ったコンストラクタの呼びなおしにも当てはまります。


superを使ったコンストラクタの呼びなおし時

superを使ったコンストラクタの呼びなおしも同じです。

例えば下のような親クラスがあったとします。

class ParentClass{
  ParentClass(){
    //親のコンストラクタ1
  }
  ParentClass(int num){
    //親のコンストラクタ2
  }
}

この時、子クラス側のコンストラクタで、以下のようにsuperによるコンストラクタ呼びなおしの前に他の処理を行っているとコンパイルエラーです。

class ErrorSample extends ParentClass{
  //コンストラクタ
  ErrorSample(){
    System.out.println(); //先に処理が行われている☆
    super(2); //コンストラクタ2を呼び出しているが・・・★
  }
}

以下のように、先にコンストラクタの呼びなおしが行われていれば問題ありません。

class NonErrorSample{
  NonErrorSample(){
    super(2); //先にコンストラクタ2を呼び出している★
    System.out.println(); //☆
  }
}

おまけ

Javaの試験ではよく以下のようにthis()とsuper()が並んでいる場合があります。

class SubClass extends SuperClass{
  SubClass(){
    this();
    super();
  }
  //省略
}

this()もsuper()も、どちらもそれより前に処理が実行されるとコンパイルエラーとなります。したがって、この2つが続けて並んでいると、どちらが先でもコンパイルエラーです。

また、たまにタイピングミスで以下のように書いてしまう場合がありますが、これもコンパイルエラーです。

class SubClass extends SuperClass{
  SubClass(){
    ; //処理内容は無いが、;で1つの処理を行っているとみなされる
    super();
  }
}

まとめ

・thisやsuperでコンストラクタを呼びなおすことができる
・コンストラクタの呼びなおしはコンストラクタの先頭で行う必要がある。


次回

次回はデフォルトコンストラクタと継承に関する注意点について扱います。


はじめてのJavaシリーズの目次はこちら
クラスの継承編はこちら


java 11 の練習問題一覧はこちら
はじめてのJavaシリーズの練習問題一覧はこちら