@CAT_IS_ME (猫は私。)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Javaのオーバーライドについて

Javaのオーバーライドについて

Javaでオーバーライドが成立する条件について質問があります。
疑問点や追加の疑問点、さらには現在の理解にて間違っているところがありましたら、教えていただきたいです。

疑問点

以下のようなコードがあった時に、

Bクラスのtest()メソッドが、アクセス修飾子の条件を満たしてないため、Aクラスのtest()メソッドをオーバーライドできないことは分かるのですが、
Cクラスのtest()メソッドはBクラスのtest()メソッドをオーバーライドしようとして、出来ずに(privateなため)Aクラスのtest()メソッドをチェックしに行って、オーバーライドするということはないのでしょうか。

ソースコード

class A
    public void test()
        System.out.println("A");
    

class B extends A
    private void test()
        System.out.println("B");
    

class C extends B
    public void test()
        System.out.println("C");
    

現在の理解

  • オーバーライドは、差分プログラミングの観点から、親クラスで定義されているメソッドを、子クラスの差分で再定義し直すこと。
  • そのため、アクセス修飾子がprivateで、子クラスから見えない場合、再定義にはならずに同名のメソッドを作成したことになる。
  • また、オーバーライドは常に、継承した親クラスの(アクセス修飾子の関係で)見られるメンバーに対して行われる
  • Bクラスのtest()メソッドは、コンパイラの構文解析を突破して意味解析でコンパイルエラーになっているので、Bクラスのtest()メソッドが書かれていない時とは状況が異なる。
  • もし、Bクラスのtest()メソッドがなければ、Cクラスのtest()メソッドは、Aクラスのものをオーバーライドする。
  • アノテーションをつけない限り、コンパイラは、こちらがオーバーライドしたいと思っていることを理解しないため、同名のメソッドを定義して矛盾が生じなくなった時点でコンパイルを通す

追加の疑問点

  • そもそも、オーバーライドの条件で「アクセス修飾子が自分より厳しいとダメ」があるのはなぜなのでしょうか。
  • 仮にBクラスのprivateなメソッドとCクラスのpublicなメソッドで同名のメソッドが発生したとして、問題が生じるのは「B型のインスタンスでtest()メソッドを呼び出す時」にどっちを呼び出すか分からずにコンパイルエラーが出る時のみでしょうか。
  • C型のインスタンスを生成する時に、コンストラクタチェインでAクラスの中身も見に行っているような気がするのですが、アノテーションをつけてオーバーライドを指定した時はBがダメだったらAという風に遡ってくれないのはなぜですか。
0 likes

2Answer

そもそも、オーバーライドの条件で「アクセス修飾子が自分より厳しいとダメ」があるのはなぜなのでしょうか。

アクセス(触って)して欲しくないプライベートメソッドだから、単にエラーを吐いたということです。

プライベートに指定されたメソッドってのは、ある意味開発者から「さわるな!」という警告のようなもので、それは当然継承にも関係してくることです。禁止されたメソッドにオーバーライドしようとしたからコンパイラが止めようとしてくるのです。

仮にBクラスのprivateなメソッドとCクラスのpublicなメソッドで同名のメソッドが発生したとして、問題が生じるのは「B型のインスタンスでtest()メソッドを呼び出す時」にどっちを呼び出すか分からずにコンパイルエラーが出る時のみでしょうか。

BがダメだったらAという風に遡ってくれない

コンパイラが解らないのでは無く、明確に禁止されていることを強行したから結果止められたのです。理由は同上。

@Overrideは必須ではありません(確か互換的な理由があったかと思います)が、見た目、エラーへの気づきの点から付けておくことは良いことです。
コンパイラがもうちょっとだけ詳しいメッセージをつけるだけで、根幹的な問題は変わりません。

0Like

オーバーライドの条件で「アクセス修飾子が自分より厳しいとダメ」

子クラスのインスタンスを親クラス名の変数で保持してtestを実行した場合でも子クラスのメソッドが呼ばれる。Template Methodとかで使われるが、アクセス修飾子変えられると実行時に困るからコンパイルエラーになる。

0Like

Comments

  1. @CAT_IS_ME

    Questioner

    回答ありがとうございます。
    親クラスのメソッドのアクセス修飾子を見て使いたいので、アクセス修飾子のチェックのために毎回子クラスを確認しにいくのは、汎化や多態性の趣旨から逸れてしまうのでそういう仕様になっている。という理解で合ってますでしょうか。

Your answer might help someone💌