super()の連鎖

super()の連鎖

このレッスンでできるようになること。コンストラクタが実際にどの順番で走るのかを追えるようになり、暗黙の super() が原因のコンパイルエラーを見抜けるようになります。

コンストラクタの1行目に何も書かないと、コンパイラが引数なしの super() を勝手に挿し込みます。この見えない1行が試験のほぼすべての仕掛けの正体です。

class A { A() { System.out.print("A"); } } class B extends A { B() { System.out.print("B"); } } class C extends B { C() { System.out.print("C"); } } new C();

出るのは ABC です。C の中で super() が呼ばれ、その B の中でまた super() が呼ばれ、A まで登り切ってから戻りながら実行されるので、親から先に終わります。

引数なしのコンストラクタが無いとき

ここが最大の罠です。親が引数ありのコンストラクタだけを持つと、コンパイラは引数なしの既定コンストラクタを作りません。すると子の暗黙の super() が呼ぶ相手を失い、子の側がコンパイルエラーになります。子が書かれていないのにエラーが子に出るので、原因を親だと気づけるかが分かれ目です。直し方は、子で明示的に super(値) を書くことです。

1行目にしか書けない

super(...)this(...) はどちらもコンストラクタの最初の文でなければならず、1つのコンストラクタで両方は書けません。this(...) を書いた場合は同じクラスの別のコンストラクタへ渡り、その先で親が呼ばれます。

なお初期化の順番は、親のコンストラクタが終わってからフィールド初期化子と初期化ブロック、そのあと自分のコンストラクタ本体です。親のコンストラクタから子のオーバーライドされたメソッドを呼ぶと、子のフィールドがまだ初期値のままで見える、という有名な事故もここから来ています。

演習では、呼び出しの順番をログとして組み立てて確かめます。

要件

  1. kind1 のときだけ B を、それ以外は C を生成する
  2. 生成の前に log を空にする
  3. クラス ABC は変更しない

入出力例

trace(1)"A5B" trace(2)"A5BC"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.java
学習モード

メモ

super()の連鎖

⌘S で保存