Полиморфизм в Java

Полиморфизм в Java: один интерфейс — разное поведение. Разберём, как ссылка родительского типа вызывает методы потомков.

Полиморфизм (от греч. «много форм») — способность объектов разных классов отвечать на один и тот же вызов по-своему. Код работает с общим типом, а конкретное поведение определяется реальным объектом.

Ссылка родителя на объект потомка

Переменной родительского типа можно присвоить объект любого потомка. При вызове переопределённого метода выполнится версия реального объекта, а не типа переменной.

class Shape {
    double area() {
        return 0;
    }
}

class Circle extends Shape {
    double r;
    Circle(double r) { this.r = r; }
    @Override
    double area() {
        return 3.14159 * r * r;
    }
}

class Square extends Shape {
    double side;
    Square(double side) { this.side = side; }
    @Override
    double area() {
        return side * side;
    }
}

Единый код для разных типов

Главная польза: можно работать с массивом разных фигур через общий тип Shape — и каждая посчитает свою площадь сама.

Shape[] shapes = {
    new Circle(2),
    new Square(3)
};

for (Shape s : shapes) {
    System.out.println(s.area());   // вызовется нужная версия area()
}

Вывод:

12.56636
9.0

Это и есть сила полиморфизма: добавив новый класс Triangle extends Shape, цикл выше менять не нужно — он сразу заработает с новой фигурой.

Динамическое связывание

Java определяет, какой метод вызвать, во время выполнения, по реальному типу объекта — это называют динамическим связыванием. Поэтому s.area() в цикле даёт разные результаты, хотя тип переменной один.

Shape s = new Circle(1);
System.out.println(s.area());   // 3.14159 — версия Circle

s = new Square(2);
System.out.println(s.area());   // 4.0 — версия Square

Вывод:

3.14159
4.0

Коротко

  • Полиморфизм — один вызов, разное поведение в зависимости от реального объекта.
  • Переменной родительского типа можно присвоить объект потомка.
  • Вызывается версия метода реального объекта (динамическое связывание).
  • Позволяет писать код, работающий с целым семейством классов через общий тип.
Проверьте себя
1. Что произойдёт при вызове переопределённого метода через ссылку родительского типа?
AВызовется версия родителя
BОшибка компиляции
CМетод не вызовется
DВызовется версия реального объекта
2. В чём практическая польза полиморфизма?
AУскоряет программу
BУменьшает размер файла
CЗапрещает наследование
DПозволяет работать с семейством классов через общий тип
3. Когда Java определяет, какую версию метода вызвать при полиморфизме?
AПри компиляции
BПри объявлении переменной
CНикогда — выбирает программист
DВо время выполнения, по реальному типу объекта