0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Java Gold】継承絡みのメソッド呼び出しを整理させてくれ

Posted at
Sample.java
public interface A {
    void test();
}

public class B implements A {
    public void test() {
        System.out.println("B");
    }
    public void specificMethod() {
        System.out.println("Specific to B");
    }
}

public class Main {
    public static void main(String[] args) {
        A a = new B();
        a.test();               // OK: 実行結果は"B"
        a.specificMethod();     // NG: コンパイルエラー
    }
}

早速ですが、上の結果に違和感はありませんか?
ないならここから先は読む必要がありません。

  • A型なのになんでBクラスのtest()が呼ばれてるんだろう?
  • new B()してるのになんでBクラスのspecificMethod()を呼べないんだろう?

これがあやふやになってる人は読んでください。

なぜA型なのにBクラスのtest()が呼ばれているの?

Javaにおいて、変数の型(コンパイル時の型) と 実際のインスタンス(実行時の型) は区別されます。今回の例では変数 aA 型ですが、実際のインスタンスは new B() で作られているため、JVMは実行時の型 である Btest() メソッドを呼び出します。
このように、オーバーライドされたメソッド呼び出しは実行時型を基準に決まる(動的バインディング) ため、Atest() ではなく Btest() が呼ばれるというわけです。

A a = new B(); 
a.test(); // 実行時にBクラスのtest()が呼ばれる

どうしてコンパイル時と実行時で違いが出るの?

コンパイル時:

変数 aA 型として扱われるため、「a から呼び出せるメソッド = A に定義されているメソッド」と判断される。

実行時:

実際には new B() で作成されたインスタンスなので、「呼び出すメソッド本体 = B でオーバーライドした test()」が使われる。

Javaのメソッド呼び出しは基本的に「変数の型」ではなく「実行時のオブジェクト型」をもとにどのメソッドを呼ぶかが決定されます。これが「動的バインディング(ポリモーフィズム)」というやつらしいです。

なぜnew B()してるのにBクラスのspecificMethod()を呼べないの?

一方で、メソッドが呼び出せるかどうか は コンパイル時 に「この変数の型が何か」によって決まります。変数 aA 型なので、コンパイラが「A に定義されていないメソッドを呼び出してるやんけ:rage:」と判断し、コンパイルエラー となります。

A a = new B();
a.specificMethod(); // コンパイルエラー: AにはspecificMethod()がない

じゃあ呼びたい場合はどうするの?

B クラスのメソッドを呼びたいのであれば、以下のように変数の型を B にするか、キャスト によって B 型であることを保証する必要があります。

// 方法1. 変数をB型にする
B b = new B();
b.specificMethod(); // OK

// 方法2. キャストを使う
A a = new B();
((B)a).specificMethod(); // OK (実行時に本当にB型か確認される)

実際には aB 型のインスタンスであるときだけ (B)a は成功します。
もし他の実装クラス(例: Cクラス)だった場合は ClassCastException が発生します。

まとめ

  • 実行時のメソッド呼び出しは、実行時の型が優先される(動的バインディング)。

⇒ だから A 型変数でも Btest() が呼ばれる。

  • コンパイル時のメソッド参照は、変数の型にあるメソッドしか呼べない。

⇒ だから A 型変数では A インターフェースにないメソッド specificMethod()を呼べない。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?