super
「今より一つ内側のインスタンス部分」を表す予約語」
【説明】
つまり、子クラスのインスタンスから、親クラスのインスタンスのメンバにアクセスして、値を参照する必要があるときにsuperが使用されます。
【メリット】
親インスタンス部分 のメソッドやフィールドに、小インスタンスからアクセスすることが出来る。
【特徴】
「親の親」インスタンス部分へのアクセスは出来ない
下記のような継承関係の3つのクラスを例えにします。
Cクラスから生成されたインスタンスは3種構造になり、この時一番外側に相当するCインスタンスについて考えます。
Cクラスのメソッドは、一番外側のインスタンス部分(自分自身)には this, そして親インスタンス部分へは super でアクセスが出来ます。
しかし、残念ながら親の親に当たるAクラスのインスタンスにはアクセスする手段が準備されていないため、C → A にはアクセスが出来ないということです。
【使用場面】
サブクラスで オーバーライド(親クラスのメソッドを子クラスで継承)された変数やインスタンスを参照する時に使用される。
superをつけないと?
例えば、親クラスに「attack()」 というメソッドがあり、子インスタンスからアクセスしようとする場合を例でいうと、結論、
super をつけないと**「外側で attack() を呼び続ける無限ループ」になってしまいます。**
super をつけないということは**this.attack
**と同じ意味になってしまうためです。
thisは「自分自身のインスタンスという意味」で、より正確には、「インスタンスの最も外側部分」を言う意味であるため上記の通り、メソッドの無い部分をずっとつづけることになる、ということになります。
【書き方】
コンストラクタをオーバーライドする際は1行目に「super()」と記述する必要があります。
親インスタンス部分のフィールドを利用する時
super.フィールド名
親インスタンス部分のメソッドを呼び出す時
super.フィールド名([引数])
【サンプルコード】 super で親クラスのコンストラクタを呼び出す
【Main.java】
public class Main {
public static void main(String[] args) throws Exception {
// SubClassの コンストラクタ を呼び出す。
SubClass sbc = new SubClass(); // 出力結果はSubClass.javaで格納された値によって変わる
}
}
【SuperClass.java】
親クラスです。ここでメソッドを定義しています。
class SuperClass {
public SuperClass() {
System.out.println("Super_Const");
}
public SuperClass(String str) {
System.out.println("文字列型の引数: " + str);
}
// int型の場合のメソッド
public SuperClass(int num) {
System.out.println("int型の引数: " + num);
}
}
【SubClass.java】
こちらは子クラス。extendsで 親クラスの SuperClassを継承しています。
コンストラクタから、superを使用して引数で文字列"apple"を指定。
int型のコンストラクタを呼び出したい場合は、super(int型)を指定します。
// 親クラスの SuperClass を継承
class SubClass extends SuperClass {
public SubClass(){ // コンストラクタ 定義
super("サブクラスで文字列型の引数を格納"); //super を使用して 文字列の 引数を指定。
}
}
【実行結果】
文字列型の引数: サブクラスで文字列型の引数を格納
【SubClass.java】
ここで引数を 文字列型 → int型 にして出力すると出力結果が変わります。
// 親クラスの SuperClass を継承
class SubClass extends SuperClass {
public SubClass() { // コンストラクタ 定義
super(200000); // super を使用して int型の 引数を指定。
}
}
【実行結果】
int型の引数: 200000
【まとめ】
super は オブジェクト指向を学ぶ上で超重要な要素なので、今後もわかるまで更新を続けます。