2015-09-15 2 views
0

Код:Поскольку компилятор вызывает метод, основанный на ссылочном типе, а не фактический тип объекта, почему вызов метода объекта вызывается?

public class X 
{ 
    public void methodA() //Base class method 
    { 
     System.out.println ("hello, I'm methodA of class X"); 
    } 
} 

public class Y extends X 
{ 
    public void methodA() //Derived Class method 
    { 
     System.out.println ("hello, I'm methodA of class Y"); 
    } 
} 

public class Z 
{ 
    public static void main (String args []) { 
     X obj1 = new X(); // Reference and object X 
     X obj2 = new Y(); // X reference but Y object 
     obj1.methodA(); 
     obj2.methodA(); 
    } 
} 

Выход:

hello, I'm methodA of class X 
hello, I'm methodA of class Y 

Метод от типа объекта становится вызывается вместо ссылочного типа. Разве это не значит, что в обеих линиях это должно быть?

hello, I'm methodA of class X 
hello, I'm methodA of class X 
+1

Может быть, ваше первое предположение неверно ... что это весело, учитывая, что вы правильно мечение вашего вопроса [тег: полиморфизм] – dotvav

+0

@HovercraftFullOfEels моих плохого. Я имел в виду, что компилятор решает, можно ли вызвать метод. –

ответ

1

Компилятор выбирает сигнатуру метода, который наилучшим образом соответствует вызов метода (из всех перегруженных методов с одинаковыми именами, которые доступны для компиляции типа временной переменной, для которого вызывается метод).

Однако метод, который фактически выполняется, определяется только во время выполнения на основе типа времени выполнения экземпляра, на который ссылается переменная, для которой вызывается метод. Это то, что метод переопределяет.

Возможно, вы перепутаете перегрузку метода (выполняемую во время компиляции) с переопределением метода (выполняется во время выполнения).

1

Это очевидно. когда вы снова объявляете methodA() в подклассе. methodA() суперкласса переопределяется. Итак, всякий раз, когда вы вызываете methodA(), вызывается methodA() подкласса.

X obj1 = new Y(); 
Y obj2 = new Y(); 
obj1.methodA(); 
((X)obj2).methodA(); 

оба вызову метод overriden.

В java нет способа вызвать метод, который переопределяется. Только что вы можете сделать, чтобы вызвать метод суперкласса, а переопределение функции заключается в следующем:

public void methodA() { //Derived Class method 
    super.methodA(); 
    // add other stuff if you want here 
} 
1

Java использует «раннее связывание», т.е. связывая имя методы во время компиляции, и «динамическая отправка», выбор методы реализация наиболее тесно связана с типом объекта во время выполнения. Java использует ссылочный тип при связывании, потому что тип объекта не может быть известен во время компиляции.

X obj1 = new X(); // obj1 is bound to X and of type X 
if (i == 0) { 
    obj1 = new Y(); // obj1 is still bound to X, but now of type Y 
} 
obj1.methodA();  
// Due to early binding, a compiler error occurs if X doesn't contain methodA 
// Due to dynamic dispatch, if it exists, the methodA of obj1's type will be used. Otherwise the closest superclass's methodA will be used. 
Смежные вопросы