@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

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

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

0Like

Comments

  1. @CAT_IS_ME

    Questioner

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

  2. 汎化や多態性の趣旨から逸れてしまうのでそういう仕様になっている。

    Javaはそういう仕様。
    C++はB型では呼べないがBインスタンスのA型保持は呼べる(Bメソッドが実行)で行けるようなのでおそらくあなたの想定通り。ただできるとしても継承前提で設計するなら止めてほしいとは思う。

>そもそも、オーバーライドの条件で「アクセス修飾子が自分より厳しいとダメ」があるのはなぜなのでしょうか。
>アノテーションをつけてオーバーライドを指定した時はBがダメだったらAという風に遡ってくれないのはなぜですか。

そういう紛らわしいコード(呼び出すtestが親(あるいは子)のなのか自分のなのか解りづらいコード/クラス)は書けないようになっています。それがJava流。同等のことをしたかったら別名にしたら、みたいな。

>こちらがオーバーライドしたいと思っていることを理解しないため、同名のメソッドを定義して矛盾が生じなくなった時点で
public/protectedでfinalを付けていない以上、コンパイラはoverride対象と扱います。

0Like

Your answer might help someone💌