Developer

【はじめてのJava】コラム:変数名にsuperを付ける【クラスの継承編】
2022.02.27
Lv1

【はじめてのJava】コラム:変数名にsuperを付ける【クラスの継承編】

はじめてのJava

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


クラスの継承編

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

こちらの記事では変数名にsuperを付ける場合について扱いました。

その際に「同名で変数を定義すると混乱のもと」と書きました。そうなると変数にsuperを付ける理由が無くなるように感じます。今回は「変数にsuperを付ける場合があるのか」について扱います。


目次


thisとsuper

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

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

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

 


変数にsuperを付ける

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

しかしその際に、親クラスと子クラスで同名のインスタンス変数を定義すると混乱のもととも記載しました。

では、それ以外にインスタンス変数にsuperを明示的につける場面はあるのでしょうか。

実は親クラスと子クラスで同名の変数が定義されていない場合に、あえて変数名にsuperを付けることはあり得ます。

どういうことでしょうか。


可読性への配慮

実は可読性を考慮した際に変数にsuperを付ける可能性はあります。

それは子クラス側で、親クラス側にのみ定義されている変数であることを明示したい場合です。

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

//親クラス
class Animal{
  double weight; //体重、親クラスでのみ定義
}

//子クラス
class Cat extends Animal{
  void eat(){
    weight += 10;
  }
  void walk(){
    weight -= 5;
  }
}

親クラスのAnimalクラスではインスタンス変数weightが定義されています。そして、子クラスのCatクラス内のメソッドでweightの値が増減しています。このソースコード自体は問題なさそうです。

では、このクラスの作成者と別の人がCatクラスのeatメソッドのソースコードの改修をする場合を考えてみましょう。

改修作業はまず、メソッド内の動作を追うところから始まるはずです。当然weightがどこに定義されてるのかも考えることになります。
しかし変数weightは親クラスであるAnimalクラスでのみ定義されています。

改修しようとした人の目線では「Catクラス内には存在しない変数weightを操作してる(コンパイルエラーだ!!)」とか「どこにも書かれていない変数weightの値を操作している・・・どういうことだろう?」といった印象を受ける可能性があります。

この場合、変数weightを探すだけでかなり時間がかかる可能性があります。

上記の例程度のコード量であれば、「いやいやいや、親クラスのAnimalクラスに書いてあることぐらいわかるでしょう。」となるかもしれません。しかし、もし関係するクラスが複数あり、各クラスのソースコードも100行単位だった場合はどうでしょうか。ソースコード全体に目を通すだけでもかなりの時間がかかりそうです。

このようなことまで考慮すると「親クラスで定義されている変数であることを明示的に示すためにsuperを付ける」ことで可読性を上げるということもあり得ます。そうすることで大量にあるソースコード全てに目を通すのではなく、まずは親クラスから見てみる、という形で方針を定めることができます。

今回の場合、superを付けた場合のCatクラスは以下の通りになります。weightはCatクラスの中では定義されていませんが、super.weightと書いてあるため、ぱっと見でも親クラスを見れば定義が見つかるかも、と推測が効きやすくなります。

//親クラス
class Animal{
  double weight; //体重、親クラスでのみ定義
}

//子クラス
class Cat extends Animal{
  void eat(){
    //weight += 10;
    super.weight += 10;
  }
  void walk(){
    //weight -= 5;
    super.weight -= 5;
  }
}

おまけ

このような可読性に関わる話は「絶対の正解」はありません。例えば普段superを付けていないルールを採用しているチームの人からすると逆に「なぜsuperがついているの?」となる可能性もあります。
重要なのは「チーム内でルールを統一しておくこと」「そのチームのルールをしっかりと把握しておくこと」です。

 


まとめ

・親クラスで定義されているインスタンス変数であることを明示する場合にsuper.変数名とすることもあり得る。
・可読性に関する話は「絶対の正解」は、ない。
・大切なのはチーム内でのルールを正確に把握し、守ること。


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


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