Java言語の継承とは?コンストラクタとは?オーバーライドとは?初心者向けに演習問題のサンプルコードをもとにしてわかりやすく説明します。その①

本記事にはプロモーションが含まれています。

軽くて安いのに大容量!カフェ作業も捗る!プログラミングに最適なPCをお探しなら【おすすめはこちら

演習問題

  • class X{
  • X() {System.out.println(“[X]”);}
  • void a() { System.out.println(“[x.a]”); }
  • void b() { System.out.println(“[x.b]”); }
  • }
  • class Y extends X {
  • Y() { System.out.println(“[Y]”); }
  • void a() { System.out.println(“[y.a]”); }
  • }

上記のようにクラスX,Yが宣言されている場合、以下のプログラムコードが実行された結果を予測しましょう。

 

  • X x = new X();
  • x.a();
  • x.b();
  • Y y = new Y();
  • y.a();
  • y.b();

上のプログラムコードですが、クラスXとクラスYには

「X()  Y()」

という引数のないコンストラクタが定義されています。

そして処理の内容はそれぞれ「X」「Y」を出力するという内容になっています。

 

それぞれのなかにメソッドが定義されています。

このプログラムの内容を下の内容で実行します。

もちろんそのままでは実行できないのでメインクラスを設定して実行します。

 

実行側はまずXクラスをインスタンス化してメソッドを実行します。

Yクラスも同様にインスタンス化してメソッドを実行します。

継承はまず子クラスの中身が優先されます。

親クラスの「X」クラスの中にも「a」というメソッドがありますが、はじめにYクラスの中の「a」というメソッドが優先的に実行されます。そして次に「b」メソッドを実行します。

Yクラスには独自で定義している「b」メソッドはありません。

ですが「Xクラス」を継承しているのでそれを呼び出して実行するという流れになるはずです。

 

実際にこのような流れになるかどうかプログラムを実行してみたいと思います。

 

プログラムコード

 

  1. class X {
  2. // Xクラスのコンストラクタ
  3. X() {
  4. System . out . println ( “[X]” ) ;
  5. }
  6. // Xクラスのaメソッド
  7. void a() {
  8. System . out . println ( “[x.a]” ) ;
  9. }
  10. // Xクラスのbメソッド
  11. void b() {
  12. System . out . println ( “[x.b]” ) ;
  13. }
  14. class Y extends X {
  15. // Yクラスのコンストラクタ
  16. Y() {
  17. System . out . println ( “[Y]” ) ;
  18. }
  19. // Yクラスのaメソッド
  20. void a() {
  21. System . out . println ( “[y.a]” ) ;
  22. }
  23. // 本体側のメインクラス
  24. class Main {
  25. public static void main(String[] args) {
  26. X x = new X();
  27. x.a();
  28. x.b();
  29. Y x = new Y();
  30. y.a();
  31. y.b();
  32. }
  33. }

実行結果

  1. [X]
  2. [x.a]
  3. [x.b]
  4. [X]
  5. [Y]
  6. [y.a]
  7. [x.b]

解説

親クラス「Xクラス」の挙動

親クラスである「Xクラス」のコンストラクタが定義されました。

このコンストラクタの処理内容は[X]を出力することです。

 

  1. X() {
  2. System . out . println ( “[X]” ) ;
  3. }

「Xクラス」の中にaメソッドとbメソッドが定義されそれぞれの処理内容が記述されています。

 

  1. // Xクラスのaメソッド
  2. void a() {
  3. System . out . println ( “[x.a]” ) ;
  4. }
  5. // Xクラスのbメソッド
  6. void b() {
  7. System . out . println ( “[x.b]” ) ;
  8. }

子クラス「Yクラス」の挙動

「Yクラス」は親クラスである「Xクラス」を継承するクラスです。extendsを記述します。

 

  1. class Y extends X {

コンストラクタとメソッドを定義してそれぞれの処理内容を記述します。

 

  1. // Yクラスのコンストラクタ
  2. Y() {
  3. System . out . println ( “[Y]” ) ;
  4. }
  5. // Yクラスのaメソッド
  6. void a() {
  7. System . out . println ( “[y.a]” ) ;
  8. }

Y() { System.out.println(“[Y]”); }

子クラスのコンストラクタが実行されるときに親クラスのコンストラクタを明示的に呼び出していないので仮想的に

Y() { super();System.out.println(“[Y]”); }

親クラスのコンストラクタが追加されます。

記述していなくても仮想的に追加されるということです。

 

どういうことかというとまず親クラスのコンストラクタを実行して次に子クラスのコンストラクタの内容を実行するということです。

super();

というのは親クラスのコンストラクタです。

つまりXクラスのコンストラクタの内容の[X]の出力が終わってからやっと「Yクラス」のコンストラクタの内容の実行に移るということです。

 

「Yクラス」独自のメソッドaですが

void a() { System.out.println(“[y.a]”); }

親クラスも同じメソッドaを持っています。

ですがオーバーライドが発生して、呼び出されてもこちらの方が優先して実行されるということになります。

[y.a] が出力されるということです。

 

メインクラスの挙動

まず「Xクラス」のインスタンス化がおこなわれます。

このインスタンス化がおこなわれた時点で自動的に「Xクラス」のコンストラクタが実行されます。

 

  1. X x = new X();

次に「Xクラス」のaメソッドとbメソッドを呼び出します。

すると「Xクラス」のaメソッドとbメソッドの内容が実行されます。

つまり[x.a]と[x.b]が出力されます。

 

  1. x.a();
  2. x.b();

続いて「Yクラス」のインスタンス化をします。

この時点で自動的に「Yクラス」のコンストラクタが実行されますがその時点で仮想的に「Xクラス」のコンストラクタが実行されます。

つまり一番はじめに「Xクラス」のコンストラクタが実行されるということです。

「Xクラス」のコンストラクタの内容である

[X]

が先に出力されるということになります。

 

  1. Y x = new Y();

y.a();

で「Yクラス」のaメソッドを呼び出します。「Xクラス」のaメソッドと名前が同じなためオーバーライドが発生し子クラスのaメソッドが優先して実行されます。

 

  1. y.a();
  2. y.b();

y.b();

「Yクラス」はbメソッドを持っていないため、「Xクラス」のbメソッドの内容が出力されます。

 

まとめ

この問題のややこしい所は子クラスである「Yクラス」のコンストラクタが実行されるときには自動的に「Xクラス」のコンストラクタも一緒についてくるというところです。

 

なので[Y]が出力される前に必ず[X]が出力されることを理解してください。

記述されてはいませんが

Y() { super();System.out.println(“[Y]”); }

が隠れていることを理解しましょう。

 

参考資料

 


スッキリわかるJava入門第3版 [ 中山清喬 ]


Java 第2版 入門編 ゼロからはじめるプログラミング【電子書籍】[ 三谷純 ]


Java 第3版 入門編 ゼロからはじめるプログラミング (プログラミング学習シリーズ) [ 三谷 純 ]


Java 第2版 実践編 アプリケーション作りの基本 (プログラミング学習シリーズ) [ 三谷 純 ]


いちばんやさしいJavaの教本 人気講師が教えるプログラミングの基礎/石井真/カサレアル【3000円以上送料無料】

タイトルとURLをコピーしました