Я знаю синтаксическую разницу между переопределением и перегрузкой. И я также знаю, что переопределение - это полиморфизм во время выполнения, а перегрузка - это полиморфизм времени компиляции. Но мой вопрос: "Является ли перегрузка действительно полиморфизмом времени компиляции? Является ли вызов метода действительно решающим во время компиляции?". Чтобы прояснить мою точку зрения, рассмотрим примерный класс.
public class Greeter {
public void greetMe() {
System.out.println("Hello");
}
public void greetMe(String name) {
System.out.println("Hello " + name);
}
public void wishLuck() {
System.out.println("Good Luck");
}
}
Поскольку все методы greetMe(), greetMe(String name), wishLuck()
являются общедоступными, все они могут быть переопределены (в том числе перегружены), правильно? Например,
public class FancyGreeter extends Greeter {
public void greetMe() {
System.out.println("***********");
System.out.println("* Hello *");
System.out.println("***********");
}
}
Теперь рассмотрим следующий фрагмент:
Greeter greeter = GreeterFactory.getRandomGreeter();
greeter.greetMe();
Метод getRandomGreeter()
возвращает случайный объект Greeter
. Он может либо возвращать объект Greeter
, либо любой из его подклассов, например FancyGreeter
или GraphicalGreeter
или любой другой. getRandomGreeter()
создаст объекты либо с помощью new
, либо динамически загрузит файл класса и создаст объект с использованием отражения (я думаю, что это возможно с отражением) или любым другим способом, который возможен. Все эти методы Greeter
могут или не могут быть переопределены в подклассах. Поэтому компилятор не имеет возможности узнать, переопределен ли какой-либо конкретный метод (перегружен или нет). Правильно? Кроме того, wikipedia говорит о Виртуальные функции:
В Java все нестатические методы по умолчанию являются "виртуальными функциями". Только методы, отмеченные ключевым словом final, которые нельзя переопределить, наряду с частными методами, которые не унаследованы, не являются виртуальными.
Так как виртуальные функции разрешаются во время выполнения с помощью диспетчеризации динамических методов, и поскольку все не частные, но не окончательные методы являются виртуальными (независимо от того, перегружены они или нет), они должны быть разрешены во время выполнения. Правильно?
Затем, как перегрузка может быть разрешена во время компиляции? Или, есть ли что-то, что я неправильно понял, или мне не хватает?