Динамическая отправка метода в 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);
}
}
поскольку у A нет переменной b внутри него, даже когда вы передаете B в A, у вас все еще есть объект A, в котором нет переменной b. Таким образом, попытка доступа к b даст вам ошибку времени компиляции.
в случае show (), A и B оба имеют этот метод, поэтому то, что вы делаете здесь, на самом деле переопределяет его во время выполнения. Это не что иное, как полиморфизм. Так как A уже имеет метод show (), и он переопределяется позже B,
A a = новый B(); выставка();
это запустит метод show () для B во время выполнения.