Java — какая функция вызывается, когда задействованы наследование, полиморфизм, перегрузка и переопределение?

У меня есть этот вопрос, связанный с наследованием, полиморфизмом, перегрузкой и переопределением. Я понимаю все эти термины, но не уверен, как они работают здесь. Вот код:

class A {
    public String show(D obj) {return "A and D";}
    public String show(A obj) {return "A and A";}
}
class B extends A {
    public String show(B obj) {return "B and B";}
    public String show(A obj) {return "B and A";}
}
class C extends B{}
class D extends B{}
public class whatever {
    public static void main(String[] args) {
        A a = new B(); // note the B here
        B b = new B();
        C c = new C();
        D d = new D();
        System.out.println(a.show(a)); // B and A
        System.out.println(a.show(b)); // B and A
        System.out.println(a.show(c)); // B and A
        System.out.println(a.show(d)); // A and D
    }
}

Итак, задача здесь состоит в том, чтобы найти выход. У меня уже есть ответы, это комментарии, которые я оставил.

Я понимаю первое, потому что Java автоматически выполняет динамическую привязку, поэтому a.show() вызывает show() из класса B, а a имеет тип A, поэтому вызывается B.show(A obj).

Последнее тоже имеет смысл, метод show() перегружен, и поскольку d имеет тип D, вызывается A.show(D obj), унаследованный от класса A.

С двумя другими у меня проблемы. Ну, я понимаю, что это имеет смысл, потому что b и c технически являются объектами типа A, но почему это идет с «B и A», а не с «B и B»?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Объявленный тип aA.

A имеет только два метода: один принимает A (и оба b, и c являются экземплярами A), а другой принимает D (и ни b, ни c не являются экземплярами D).

Итак, первый метод подходит, а второй нет. Таким образом, первый метод выбирается компилятором.

Этот метод переопределен в B, а конкретный тип a — B, поэтому печатается «B и A».

Метод B.show(B) не переопределяет метод A.show(A), так как он не принимает тот же тип в качестве аргумента.

О, так он сначала смотрит на объявленный тип, а затем выбирает переопределенный метод. Я думал об этом в обратном направлении, я думал, что он просто сразу смотрит на конкретный тип. Спасибо за помощь!

Karan Bijani 18.03.2019 18:46

Здесь есть две концепции: одна для перегрузки, а другая для переопределения. Когда вы создаете A a = new B(); это означает, что a является объектом B и имеет тип A . Поэтому, когда выполняется a.show(a), он сначала сталкивается с методами show(A obj) и show(B obj) класса A, а затем сопоставляет параметр с типом A, но 'a' является экземпляром B, поэтому метод show(A obj) класса B.

Теперь, когда выполняется a.show(c), он сначала встречает методы show(A obj) и show(B obj) класса A, а затем не находит совпадений с параметром типа C внутри класса A, но все равно выполняется потому что класс C расширяет B, а B расширяет A.

Подводя итог вкратце, можно сказать, что a.show(a) эквивалентен a.show(b) и эквивалентен a.show(c).

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