Полиморфизм в Java: Полное руководство с практическими примерами
Что такое полиморфизм в Java?
Полиморфизм — это ключевая концепция объектно-ориентированного программирования (ООП) в Java. Она возникает, когда классы связаны наследованием, позволяя одному интерфейсу представлять разные базовые формы. Результат: вызов метода может вызывать разные реализации в зависимости от фактического типа объекта во время выполнения.
Представьте смартфон, который может общаться голосовым вызовом, текстом, изображением или email. Цель — общение — одна, но каждый режим ведет себя по-разному. Это полиморфизм в бытовых терминах.
Что вы узнаете
- Определение полиморфизма в Java
- Практические примеры ООП
- Переопределение методов (Method Overriding)
- Перегрузка vs Переопределение (Overloading vs Overriding)
- Динамический (run-time) полиморфизм
- Статический vs Динамический полиморфизм
- Ключевое слово
super
Полиморфизм в Java ООП: Пример
Рассмотрим базовый класс Account, предлагающий deposit() и withdraw(). Два подкласса, SavingsAccount и CheckingAccount, наследуют эти методы без изменений, так как операции идентичны.

Адаптация к меняющимся требованиям
Когда требуется новая функция — например, овердрафт — подкласс PrivilegedAccount может переопределить withdraw() для предоставления новой логики без изменения существующих подклассов. Это демонстрирует преимущество полиморфизма для сопровождения.

Переопределение методов в Java
Переопределение происходит, когда подкласс предоставляет свою реализацию метода, уже определенного в суперклассе. Сигнатура метода (имя, параметры, тип возврата) должна совпадать точно.
Ключевые правила
- Переопределенный метод может иметь более широкую видимость (например,
protectedкpublic), но никогда не более узкую. - Типы возврата должны быть одинаковыми или ковариантными.
Пример:
class Doctor {
public void treatPatient() {
// общая логика лечения
}
}
class Surgeon extends Doctor {
@Override
public void treatPatient() {
// специализированная хирургическая логика
}
}
public class Run {
public static void main(String[] args) {
Doctor doctor = new Doctor();
doctor.treatPatient(); // выполняет Doctor.treatPatient()
Surgeon surgeon = new Surgeon();
surgeon.treatPatient(); // выполняет Surgeon.treatPatient()
}
}
Перегрузка vs Переопределение
| Перегрузка методов (Overloading) | Переопределение методов (Overriding) |
|---|---|
| Один класс, одно имя, разный список параметров. | Метод суперкласса переопределяется в подклассе с идентичной сигнатурой. |
Пример:void sum(int a, int b); |
Пример:class X { int sum() { ... } }
class Y extends X {
@Override int sum() { ... }
} |
Динамический полиморфизм (Run-Time)
Когда ссылка суперкласса указывает на объект подкласса, JVM разрешает вызов метода во время выполнения. Это и есть настоящий полиморфизм в действии.
Doctor doc = new Surgeon(); doc.treatPatient(); // Выполняется Surgeon.treatPatient()
Фактический вызванный метод зависит от типа объекта во время выполнения, а не от типа ссылки.
Статический vs Динамический полиморфизм
Статический полиморфизм (перегрузка) разрешается во время компиляции, тогда как динамический полиморфизм (переопределение) — во время выполнения.
| Статический полиморфизм | Динамический полиморфизм |
|---|---|
| Перегрузка методов; связывание во время компиляции. | Переопределение методов; связывание во время выполнения. |
Пример:void sum(int a, int b); |
Пример:Doctor d = new Surgeon(); |
Использование ключевого слова super
Когда подклассу нужно расширить метод суперкласса, super вызывает родительскую реализацию перед добавлением собственной логики.
class Surgeon extends Doctor {
@Override
public void treatPatient() {
super.treatPatient(); // базовая логика
// логика, специфичная для хирурга
}
}
Аналогично, super может обращаться к защищенным или публичным полям суперкласса.
Практический пример: Наследование, Полиморфизм и Super
Скопируйте код ниже в вашу IDE и наблюдайте за выводом.
public class Test {
public static void main(String[] args) {
X x = new X();
Y y = new Y();
y.m2(); // Раскомментируйте, чтобы увидеть эффекты наследования
// x.m1();
// y.m1();
// x = y; // ссылка родителя на объект ребенка
// x.m1();
// y.a = 10; // ошибка: a is private
}
}
class X {
private int a;
int b;
public void m1() {
System.out.println("This is method m1 of class X");
}
}
class Y extends X {
int c;
@Override
public void m1() {
System.out.println("This is method m1 of class Y");
}
public void m2() {
super.m1();
System.out.println("This is method m2 of class Y");
}
}
Ключевые выводы
- Полиморфизм позволяет объектам принимать множественные формы через наследование.
- Переопределение методов меняет поведение в подклассах, сохраняя ту же сигнатуру.
- Динамический полиморфизм разрешает вызовы методов во время выполнения, обеспечивая гибкий код.
- Статический полиморфизм (перегрузка) — это compile-time, динамический — run-time.
- Ключевое слово
superпозволяет подклассам вызывать методы родителя или обращаться к защищенным членам.
java
- Полиморфизм в Java: концепции, примеры и лучшие практики
- Абстрактные классы в C#: практическое руководство с примерами кода
- Интерфейсы в C#: определение, пример и практическое применение
- Метод String.length() в Java: как получить длину строки (пример)
- Понимание String.charAt() в Java: синтаксис, возвращаемый тип, исключения и пример
- Метод String.contains() в Java: как проверить наличие подстроки — примеры
- Освоение String.endsWith() в Java: проверка суффиксов строки с примерами
- Ключевое слово static в Java: переменные, методы и блоки — практические примеры
- Интерфейс vs Абстрактный класс в Java: Как выбрать правильную абстракцию
- Чтение файлов в Java с BufferedReader — Практическое руководство с примерами