目次
- はじめに
- 前提知識
- 継承クラスについて
- コンストラクタ
- 今回のキモ
- 暗黙的なコンストラクタ実行
- おわりに
はじめに
どうも駆け出しエンジニアです。
先日会社でコーディングをしていた際に人の書いたコードの続きを書かなくちゃいけなくなったんですが、
その時にクラスの継承,コンストラクタでドツボにはまってしまいかなりの時間を使ってしまいまして....
もう一回頭から学習しなおした所、わからないことがボロボロ出てきてヒドかったので再度まとめることにしました。
なお、本記事は
・「現在Javaを触っている人」
・「もう一度内容を復習したい人」
向けとなっております。
各クラス名/変数名は適宜読み替えてください。
前提知識
継承クラスについて
- 継承クラス=新しいクラスを作るとき、以前作った機能と共通する部分を引き継ぐクラス
- 継承元のクラスのことを「親クラス」、継承先のクラスのことを「子クラス」と呼ぶ。
- 同意義で「スーパークラス」「サブクラス」とも呼ぶ
※本記事ではスーパー/サブで表現。 - 継承クラスのインスタンスを作成することで、継承クラスのメソッド/フィールドにアクセスできる。
- ↓↓↓↓記述の仕方は↓↓↓↓
Super.java
class Super {
public void exampleSuper(){
//何らかの処理
}
}
Sub.java
class Sub extends Super(){ //クラス名 extends 継承元クラス名 で継承。
public void exampleSub(){
//何らかの処理
}
}
コンストラクタ
- コンストラクタ=クラスのインスタンスを作成したときに自動で必ず呼び出されるメソッドのこと
- クラス名と同じ名前のメソッドのこと
- 通例コンストラクタ名は上記理由から先頭は大文字
- 戻り値はもともと想定していないので、voidは書いちゃダメ(→コンパイルエラー)
- 主にそのクラスのフィールド(メンバ変数)を初期化するのに用いられる。
- というか通例として/暗黙的にそうらしいので、それ以外の余計なことはしない方が吉。
→大規模開発における可読性/保守性の向上につながる
- ↓↓↓↓記述の仕方は↓↓↓↓
Smple.java
class Sample{
public Sample(){
//ここがコンストラクタ
}
public void exampleMethod(){
//これはただのクラスメソッド
}
}
今回のキモ
暗黙的なコンストラクタ実行
- クラスのインスタンス化時、継承階層の最上位から下方向へ、順番にインスタンス化されていく
- サブクラスのコンストラクタは最初にスーパークラスのコンストラクタを呼び出す
- スーパークラスのコンストラクタを明示的に呼び出さないとき、自動的に引数のないコンストラクタが呼び出される。
- コンストラクタの呼び出し時はsuper()メソッドが暗黙的に(自動的に)実行されている
●super();
スーパークラスのコンストラクタを呼び出すメソッド。
サブクラスのコンストラクタは"言語実装として"暗黙的(自動的)にスーパークラスのコンストラクタを実行するので、
必ず記述が必要なものではない
- ↓↓↓↓具体例↓↓↓↓
Super.java
class Super {
Super() {
System.out.println("スーパークラスです!");
}
}
Sub.java
class Sub extends Super {
Sub() {
// 暗黙的にスーパークラスのコンストラクタが実行される
System.out.println("サブクラスです!");
}
}
Main.java
class Main {
public static void main(String[] args) {
Sub obj = new Sub();
}
//実行結果
スーパークラスです!
サブクラスです!
"暗黙的スーパーコンストラクターは未定義です"
- スーパークラスのコンストラクタが引数を持つもののみ定義されている場合、暗黙的に実行される「super();」メソッドだけではコンパイルエラー。
▽解決方法
①スーパークラスに引数を持たないコンストラクタを作成する
Super.java
class Super {
public name;
public Super(){
//コンストラクタをオーバーロードさせる
}
public Super(String name){
this.name = name;
}
}
②サブクラスのコンストラクタ内で、スーパークラスのコンストラクタの引数に合わせたsuper();メソッドで、明示的にスーパークラスのコンストラクタを呼び出す。
Super.java
class Sub {
public name;
public Super(String name){
// メイン->サブ->スーパーの順で渡ってきたname変数の値をフィールドにセット
this.name = name;
}
}
Sub.java
class Sub extends Super {
Sub(String name) {
//メインクラスのStrin型変数nameと対応->スーパークラスのコンストラクタへ受け渡し
super(name);
}
}
Main.java
class Main {
public static void main(String[] args) {
Sub obj = new Sub(String name);
}
}
終わりに
今回も長くなりましたが読んでいただきありがとうございました。
次回はtry-catchでの例外処理についてかければな~と思ってます。
では。