Динамическая отправка метода в Java

class A{
int a=10;   
public void show(){ 
    System.out.println("Show A: "+a);
    }
}

class B extends A{
public int b=20;    
public void show(){
    System.out.println("Show B: "+b);
    }
}



public class DynamicMethodDispatch {

    public static void main(String[] args) {

    A aObj = new A();       
    aObj.show();    //output - 10

    B bObj = new B();
    bObj.show();   //output - 20

    aObj = bObj;   //assigning the B obj to A..         
    aObj.show();  //output - 20 

    aObj = new B();
    aObj.show();  //output - 20
             System.out.println(bObj.b);  //output - 20 
    //System.out.println(aObj.b); //It is giving error



     }
}

В приведенной выше программе я получаю сообщение об ошибке при попытке вызвать aObj.b.
1. почему я не могу получить доступ к этой переменной через aObj, хотя она относится к классу B??
2. почему я могу получить доступ к методу show()?

5 ответов

Решение

Вы должны различать статический тип aObj и тип времени выполнения aObj,

Код такой как

A aObj = new B(); 

приводит к aObj переменная со статическим типом A и тип времени выполнения B,

Компилятор будет слишком беспокоиться о статическом типе, когда решает, что разрешить или нет.

На ваши вопросы:

1. почему я не могу получить доступ к этой переменной через aObj, хотя она относится к классу B??

Потому что (в общем случае) компилятор не может знать, что aObj будет относиться к B объект во время выполнения, только то, что он будет ссылаться на некоторую форму A объект. поскольку .b не доступно на всех A объекты, поэтому компилятор будет думать "лучше, чем потомсожалеть" и запретить его.

2. почему я могу получить доступ к методу show()?

Потому что этот метод доступен во всех A объекты (если он не объявлен в подклассе, он все еще наследуется от A).

aObj является локальной переменной типа A, A не имеет ни одного члена bвот только в вашем подклассе B, Если вы хотите использовать b, вам нужно объявить переменную типа B, но, конечно, вы можете назначить только экземпляры B (или подклассы, если таковые имеются).

A объявляет метод show(), но вы переопределяете реализацию в своем подклассе B,

Такое поведение известно как virtual method invocationи это важный аспект polymorphism на Яве. Вы должны взглянуть на этот учебник.

Методы и поля имеют различное полиморфное поведение.

Метод, который будет вызван, является методом типа времени выполнения экземпляра.

aObj=new B(); //new B()

Поле, которое будет вызываться, является полем типа ссылки, который вы объявили

A aObj = new A(); // A aObj

Следующее сработало бы, даже если в A. не было метода show ().

aObj = new B();
aObj.show(); //calls B's show()
class A{ // class A has variable a and method show();
int a=10;   
public void show(){ 
    System.out.println("Show A: "+a);
    }
}

class B extends A{ //class B inherits variables and methods of A.
   // so class B has variable a, b and show(). Also, show is overridden by class B.
public int b=20;    
public void show(){
    System.out.println("Show B: "+b);
    }
}
  1. поскольку у A нет переменной b внутри него, даже когда вы передаете B в A, у вас все еще есть объект A, в котором нет переменной b. Таким образом, попытка доступа к b даст вам ошибку времени компиляции.

  2. в случае show (), A и B оба имеют этот метод, поэтому то, что вы делаете здесь, на самом деле переопределяет его во время выполнения. Это не что иное, как полиморфизм. Так как A уже имеет метод show (), и он переопределяется позже B,

A a = новый B(); выставка();

это запустит метод show () для B во время выполнения.

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