2013-09-19 5 views
9
class One { 
    public void doThing(One o) {System.out.println("One");} 
} 

class Two extends One{ 
    public void doThing(Two t) {System.out.println("Two");} 
} 

public class Ugly { 
    public static void main(String[] args) { 
    Two t = new Two(); 
    One o = t; 
    o.doThing(new Two()); 
    } 
} 

Результат: ОдинПочему метод суперкласса называется?

class One { 
    public void doThing(One o) {System.out.println("One");} 
} 

class Two extends One{ 
    public void doThing(Two t) {System.out.println("Two");} 
} 

public class Ugly { 
    public static void main(String[] args) { 
    Two t = new Two(); 
    One o = t; 
    t.doThing(new Two()); 
    } 
} 

Результат: Два

Я знаю, что во время выполнения, даже если ссылка на объект из супер типа класса, фактический тип объекта будет известен и фактическое будет вызван метод объекта. Но если это так, то во время выполнения вызывается метод doThing(Two t), но вместо этого вызывается метод суперкласса doThing(One o). Я был бы рад, если бы кто-нибудь объяснил это

Во втором фрагменте кода он печатает «Два».

Вопрос: при вызове из суперкласса ссылки он называет doThing(One o) при вызове из класса суб ссылки он называет doThing(Two o)

ПРИМЕЧАНИЕ: Я знаю, что я нахожусь над нагрузкой и не более верхом. Я отредактировал мой вопрос для лучшей ясности.

+6

вы перегрузки, не перекрывая – nachokk

+1

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.4 – nachokk

+0

@nachokk: если вы отправили эту ссылку в качестве ответа, я бы выбрал вас как принятый ответ. Я никогда не думал о поиске спецификаций java. Thx man .., что было замечательной помощью .. –

ответ

-1

Во время компиляции выполняется поиск класса One по методу doThing(Two t), но поскольку нет метода с этой подписью, он начинает расширять поиск и находит doThing(One o). Затем он содержит двоичный файл с дескриптором one parameter whose type is One : void. Во время выполнения, так как объект, вызывающий метод, имеет тип Two, в классе Two он ищет метод, соответствующий дескриптору, и не ищет метод doThing, который принимает объект Two, поскольку он рассматривает дескриптор в двоичном файле. связывает вызов метода doThing(One o).

Спецификации java очень помогли объяснить это. here ссылка

+0

@downvoter: Пожалуйста, дайте мне знать, почему ответ не полезен ... чтобы я мог улучшить его, если это возможно. –

12

Метод doThing() имеет различный метод подписи в One и Two.

One.doThing(One one) 
Two.doThing(Two two) 

Так, подпись не совпадает, Two.doThing(Two) не Override One.doThing(One) и так o имеет тип One, One.doThing() называется.

Следует также отметить, что One.doThing(One) может принимать instance of Two в качестве аргумента для One.doThing(One) как Two extends One.

В принципе, "@nachokk - Вы Перегрузки, не Переопределение"

В первом случае, когда вы сделали

Two t = new Two(); 
One o = t; 
o.doThing(new Two()); 

Так, o является экземпляром One и Two.doThing(Two) ISN 't доступно для o, таким образом, вызывает One.doThing(One)

Вторые с cenario,

Two t = new Two(); 
One o = t; 
t.doThing(new Two()); 

t является экземпляром Two и, таким образом, называется Two.doThing(Two).

+1

Это хороший момент, но если он перегружает метод в классе 'Один', то' doThing (Два два) 'будет вызван !. – nachokk

+0

thx для ответа .. но я очень хорошо осведомлен о том, что я еще не верхом. См. Мой отредактированный вопрос .. возможно, мой предыдущий вопрос был неясен .... –

+0

@BlackPanther См. Мой обновленный ответ, надеюсь , это очень понятно. – TheKojuEffect

1

Вы просто перегрузки, как вы сказали

Two t = new Two(); 
    One o = t; 
    o.doThing(new Two()); 

Даже если реальный объект во время выполнения является два объекта, а не один объект, выбор которого перегружен метод для вызова (другими словами, подпись метода ) НЕ динамически определяется во время выполнения. Просто помните, что тип (а не тип объекта) определяет, какой перегруженный метод вызывается!

Когда вы вызываете метод doThing() с двумя объектными аргументами, вы вызываете один метод doThing() супер класса. Для метода doThing() нужен один объект и два IS-A One. Итак, в этом случае компилятор расширяет ссылку Two на объект One, а вызов завершается успешно. Ключевым моментом здесь является то, что расширение ссылок зависит от наследования , другими словами, теста IS-A.

+0

, так вы говорите, что даже если объект, вызывающий метод, имеет тип 'Two', метод, который будет выбран и привязан ссылкой, которая его вызывает? –

1

свободно книга SCJP для Java 6 состояний:

Если метод переопределяется, но вы используете полиморфный (супертип) ссылки ссылаться на объект подтипа с наиважнейшим методом, компилятора предполагает вас ', вызывающий супертипную версию метода .

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

+0

Я не понимаю, что этот метод не переопределяет. Не могли бы вы привести мне пример того, что вы говорите с кодом? – nachokk

0

Это что-то подвох
Ваших Постулаты
One o = t;
Я думаю, вы предполагаете, что класс One «о» равно двуступенно «T», который не является на самом деле равен двуступенно «T»
как класс 2 't' наследуется от первого класса, поэтому он назначит базовый класс One в вашем случае,
Таким образом, переменная 't' является ссылкой класса One и, следовательно, вызовет метод класса One.
Более создать еще один класс с именем, как класс ClassC и попытаться установить заявление
ClassC c= new ClassC()
, а затем
One o = c;
Вы получите ошибку ... надеюсь, что ответ на ваш вопрос.

+0

Я не думаю, что вы вполне понимаете мой вопрос ... –

Смежные вопросы