Developer

【はじめてのJava】thisとsuperその2【クラスの継承編】
2022.02.27
Lv1

【はじめてのJava】thisとsuperその2【クラスの継承編】

はじめてのJava

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


クラスの継承編

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

前回はthisについて扱いました。

今回はsuperについて扱います。


目次


thisとsuper

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

thisについては前回説明した通り、そのインスタンス自身を表すキーワードです。

ではsuperとはいったいどのような意味のキーワードなのか、確認してみましょう。

 


superとは

superとは 親クラス で定義されている要素を指し示すキーワードです。

具体例を見てみましょう。

 


変数の呼び出し時にsuperを付ける場合

変数の呼び出し時にsuperを付けることで、明示的に親クラスで定義されているインスタンス変数を指し示せます

例えば、以下のように、ParentClassとそれを継承したChildClassがあるとします。

ソースコードは以下の通りです。
※説明の都合でprintInfo()メソッドとコンストラクタを足してあります。

ParentClass

class ParentClass{
  int age;
  String name;

  ParentClass(){ //コンストラクタ
    age = 30;
    name = "parent";
  }
}

ChildClass

class ChildClass extends ParentClass{
  int age;
  String name;
  
  ChildClass(){ //コンストラクタ
    this.age = 20;
    this.name = "child";
  }

  void printInfo(){
    System.out.println("printInfo() in ChildClass");
    System.out.println("super.name -> " + super.name);
    System.out.println("super.age  -> " + super.age);
    System.out.println("this.name  -> " + this.name);
    System.out.println("this.age   -> " + this.age);
    System.out.println("name       -> " + name);
    System.out.println("age        -> " + age);
  }
}

ParentClassとChildClassにはそれぞれ「name」「age」という変数が定義されています。

一見するとこのようなソースコードはコンパイルエラーを引き起こしそうですが、Javaの場合はコンパイル可能です。
この場合、ChildClass内からはsuperがついているのか、thisがついているのか、何もついていないのかで、「name」「age」を呼び分けます

ChildClass内ではsuperがついている場合はParentClass内で定義されたインスタンス変数のことを指し示します
thisがついていたり、インスタンス変数名だけで呼び出している場合はChildClass内で定義された方のインスタンス変数のことを指し示します。

動作確認用のクラスを作って動作を見てみましょう。

動作確認用のクラス

public class SampleMain{
  public static void main(String[] args){
    ChildClass child = new ChildClass();
    child.printInfo();
  }
}

実行結果は以下のようになります。

確かに呼び分けがされています。


コラム:同名の変数を定義するべきか

上記のように、親クラスと子クラスで同名の変数を定義することができることはわかりました。

では、そのような実装をすべきでしょうか。

一般に そもそも親クラスと子クラスで同名の変数を定義すると混乱のもと です。

そのため、superを利用したインスタンス変数の呼び分けを前提にクラス設計を行おうとするなら、どうしてもその方針でなければならないのか、十二分に検討が必要です。

※呼び分けの必要がない場合でも、可読性のためにあえてsuper.変数名で呼び出している場合はあります。詳しくはこちらの記事をご参照ください。

 


サンプルプログラム

今回作成したサンプルプログラムは以下の通りです。動作確認用のSampleMain.javaも記載しておきます。
なお、すべて同じディレクトリに保存して動作を確認してください。

ParentClass

class ParentClass{
  int age;
  String name;

  ParentClass(){ //コンストラクタ
    age = 30;
    name = "parent";
  }
}

ChildClass

class ChildClass extends ParentClass{
  int age;
  String name;
  
  ChildClass(){ //コンストラクタ
    this.age = 20;
    this.name = "child";
  }

  void printInfo(){
    System.out.println("printInfo() in ChildClass");
    System.out.println("super.name -> " + super.name);
    System.out.println("super.age  -> " + super.age);
    System.out.println("this.name  -> " + this.name);
    System.out.println("this.age   -> " + this.age);
    System.out.println("name       -> " + name);
    System.out.println("age        -> " + age);
  }
}

動作確認用のクラス

public class SampleMain{
  public static void main(String[] args){
    ChildClass child = new ChildClass();
    child.printInfo();
  }
}

まとめ

・superとは親クラスを指すキーワード
・super.変数名とすることで親クラスのインスタンス変数を明示的に呼び出すことができる
・親クラスと子クラスで「同名の変数」を定義すると混乱のもととなるので要注意


次回

次回はsuperを使ったメソッド呼び出しについて扱います。


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


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