Почему цель для динамической отправки не определяется во время компиляции?

Сейчас я читаю книгу по Java и довольно долго застрял, размышляя о том, как работает Dynamic Method Dispatch. Я понимаю, что это мощная и ценная функция, но я не понимаю ее основной принцип. Например, у меня есть класс B, который наследуется от класса A и переопределяет некоторые из методов A. Поэтому, когда я пишу программу, я могу использовать эти выражения

A a = new B();
a.someOverridenMethod();

Я знаю, что в этой ситуации будет вызываться версия метода B, а не A. Но часть, которую я не понимаю, заключается в том, почему компилятор не может определить, какую версию (суперкласс или некоторый подкласс) метода вызвать? Я имею в виду, прямо указано, что переменная a будет содержать ссылку на объект типа B. Так почему же это можно определить только во время выполнения, даже если это явно указано в коде?

2 ответа

Решение

Вы совершенно не поняли вещь во время выполнения.

Это означает, что class A может содержать ссылку на любой из его подклассов, который будет определен во время выполнения. Их, возможно, другое утверждение, как a =new C(); после A a = new B(); и так как их может быть много операторов, как это, поэтому говорят, что версия метода будет определена во время выполнения

т.е. a будет держать ссылку на B и, возможно, в какой-то другой момент он будет содержать ссылку на C где оба B а также C подклассы A

Вот пример:

 class A {

void override()
{
    System.out.println("Inside A");
}

}

 class B extends A
{
     void override()
     {
        System.out.println("Inside B");
     }  

}

 class C extends A
 {
     void override()
     {
         System.out.println("Inside C");
     }
 }

 class Main
 {
     public static void main(String args[])
     {
         A a =new A();

         a.override();
         a=new B();

         a.override();

         a=new C();

         a.override();
     }
 }

Выход:

Inside A
Inside B
Inside C

Надеюсь, это очистит ваши сомнения.

Более ясный пример может быть:

A a = null;

if (getUserInput() == 'B')
{
  a = new B();
}
else
{
  a = new C();
}

a.overridenMethod();

Компилятор не может знать, какой метод здесь будет вызываться - он определяется пользователем во время выполнения!

Другие вопросы по тегам