Эта строка относится к тому факту, что
- перегруженные версии метода выбираются во время компиляции на основе типов времени компиляции передаваемых аргументов;тогда как
- переопределенные методы выбираются во время выполнения на основе классов объектов, для которых вы вызываете каждый метод.
Чтобы понять это различие, рассмотрим ситуацию, когдау вас есть как переопределения, так и перегрузки, например:
public class Person {
}
---------------------------------------------------------
public class Postman extends Person {
}
---------------------------------------------------------
public class Dog {
public void barkAt(Person p) {
System.out.println("Woof woof");
}
public void barkAt(Postman p) {
System.out.println("Grrrr");
}
}
---------------------------------------------------------
public class Rottweiler extends Dog {
@Override
public void barkAt(Person p) {
System.out.println("I'm going to eat you.");
}
@Override
public void barkAt(Postman p) {
System.out.println("I'm going to rip you apart.");
}
}
В этой ситуации мы вызываем один из этих barkAt
методов, например:
Dog cujo = new Rottweiler();
Person pat = new Postman();
cujo.barkAt(pat);
Теперь в данном конкретном случаеКомпилятор выбирает, будет ли cujo.barkAt(pat);
вызывать метод, подобный public void barkAt(Person p)
или public void barkAt(Postman p)
.Эти методы являются перегрузками друг друга.
Для этого компилятор проверяет тип выражения, передаваемого методу, то есть переменную pat
.Переменная pat
имеет тип Person
, поэтому компилятор выбирает метод public void barkAt(Person p)
.
Что компилятор не делает, это выбирает, является ли этот метод из Rottweiler
class или Dog
class, который вызывается.Это происходит во время выполнения на основе класса объекта, для которого вызывается метод, а НЕ на типе переменной, для которой вызывается метод.
Итак, в данном случае важен класс объекта, который называется cujo
.И в этом примере cujo
- это Rottweiler
, поэтому мы получаем переопределенную версию метода - определенную в классе Rottweiler
.
В этом примере будет напечатано I'm going to eat you
.
Подводя итог:
- Перегрузка выбирается при время компиляции на основе параметра тип .
- Переопределение выбирается при времени выполнения на основе объекта class .
Теперь возможно использовать приведение, чтобы изменить выбор перегрузки компилятора. не возможно использовать приведение для изменения выбора времени выполнения для переопределения.Таким образом, мы могли бы написать
cujo.barkAt((Postman) pat);
На этот раз передаваемый методу параметр является выражением типа Postman
.Компилятор соответственно выбирает перегрузку, и это выдает I'm going to rip you apart.
.