Обе переиспользуют имя метода, но они принципиально отличаются. Перегрузка = одно имя, разные параметры, в одном классе, разрешается на этапе компиляции. Переопределение = подкласс метод родителя с , разрешается на этапе .
Обе переиспользуют имя метода, но они принципиально отличаются. Перегрузка = одно имя, разные параметры, в одном классе, разрешается на этапе компиляции. Переопределение = подкласс метод родителя с , разрешается на этапе .
| Перегрузка | Переопределение | |
|---|---|---|
| Сигнатура | Должна отличаться (параметры) | Должна быть идентична |
| Отношение | Один класс | Родитель ↔ подкласс |
| Разрешается | Время компиляции (статически) | Время выполнения (динамически) |
| Цель | Удобство / варианты | Полиморфизм |
class Printer {
void print(String s) { System.out.println(s); }
void print(int n) { System.out.println(n); } // same name, diff param
void print(String s, int times) { /* ... */ }
}
Компилятор выбирает, какой метод print использовать, на основе типов аргументов — наследование не задействовано.
class Animal { String speak() { return "..."; } }
class Dog extends Animal {
@Override
String speak() { return "Woof"; } // replaces Animal.speak()
}
Animal a = new Dog();
a.speak(); // "Woof" — runtime picks Dog's version (dynamic dispatch)
Частая ошибка — случайно создать перегрузку, когда вы хотели переопределить метод (например, опечатка в сигнатуре). Всегда используйте @Override (Java) или override (C#), чтобы компилятор это поймал.
Переопределение — это двигатель полиморфизма — механизм времени выполнения, который делает возможным «один интерфейс, много реализаций».
Знание различия предотвращает классическую ошибку: уверенность в том, что вы заменили поведение, когда вы на самом деле создали второй, никогда не вызываемый метод.