Подтвердить что ты не робот

Ковариация и перегрузка в Java

class A {
   boolean f(A a) { return true; }
}
class B extends A {
   boolean f(A a) { return false; } // override A.f(A)
   boolean f(B b) { return true; }  // overload A.f
}

void f() {  
   A a = new A();
   A ab = new B();
   B b = new B();
   ab.f(a); ab.f(ab); ab.f(b); //(1) false, false, *false*
   b.f(a); b.f(ab); b.f(b);    //(2) false, false, true
}

Не могли бы вы объяснить первую строку последнего ложного вывода, почему это не так?

4b9b3361

Ответ 1

Не могли бы вы объяснить первую строку последнего ложного вывода, почему это не так?

Тип времени компиляции ab равен A, поэтому компилятор, который выполняет разрешение перегрузки, определяет, что единственная действительная сигнатура метода f(A a), поэтому она вызывает это.

Во время выполнения эта подпись метода выполняется как B.f(A a), потому что B переопределяет ее.

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

Ответ 2

Ну.. потому что вы вызываете тип A. Поэтому вы можете вызывать только версию f (A a). что возвращает false в B.

Ответ 3

Поскольку вы используете тип объекта A, вы можете вызывать только f (A A). Потому что B отменяет его.

Ответ 4

Не могли бы вы объяснить первую строку последнего ложного вывода, почему это не так?

Подумайте иначе: -

попробуйте комментировать ниже в классе B (главный код)

boolean f(A a) { return false; } // override A.f(A)

и добавьте syso в класс A в этом методе → boolean f(A a){....}

Затем вы увидите, что ab.f(A a) или ab.f(B b) будет вызывать метод f(A a) только класса A.

Поскольку ab имеет тип A.

Также обратите внимание: вы не сможете вызвать какой-либо метод класса B также из объекта ab.

Надеюсь, что это добавит больше разъяснений к вышеприведенным блестящим ответам.

Наконец, вы можете искать это сейчас → Почему мы назначаем родительскую ссылку на дочерний объект в Java?