Полиморфизм в Java
Полиморфизм — это способность одного и того же поведения иметь несколько различных форм или проявлений.
Полиморфизм — это один и тот же интерфейс, использующий разные экземпляры для выполнения разных операций, как показано на рисунке:
Полиморфизм — это проявление объектов в нескольких формах.
В реальной жизни, например, действие нажатия клавиши F1:
- Если вы сейчас находитесь в интерфейсе Flash, открывается справочная документация AS 3;
- Если вы сейчас находитесь в Word, открывается справка Word;
- В Windows открывается справка и поддержка Windows.
Одно и то же событие, происходящее с разными объектами, даёт разные результаты.
Преимущества полиморфизма
- 1. Устранение связанности между типами
- 2. Заменяемость
- 3. Расширяемость
- 4. Интерфейсные возможности
- 5. Гибкость
- 6. Упрощение
Три необходимых условия полиморфизма
- Наследование
- Переопределение
- Ссылка на родительский класс указывает на объект подкласса:Parent p = new Child();

void draw() {}
}
class Circle extends Shape {
void draw() {
System.out.println("Circle.draw()");
}
}
class Square extends Shape {
void draw() {
System.out.println("Square.draw()");
}
}
class Triangle extends Shape {
void draw() {
System.out.println("Triangle.draw()");
}
}
При вызове метода с использованием полиморфизма сначала проверьте, есть ли этот метод у родительского класса. Если нет, возникает ошибка компиляции; если есть, вызовите метод подкласса с тем же именем.
Преимущество полиморфизма: он может дать программам хорошую расширяемость и позволить обрабатывать все объекты классов единообразно.
Ниже приведена демонстрация примера полиморфизма. Подробное объяснение см. в комментариях:
Код файла Test.java:
Выполните приведённую выше программу, результат вывода:
eat fish catch mice eat bones guard the house eat fish catch mice
Виртуальные функции
Виртуальные функции существуют для полиморфизма.
На самом деле в Java нет понятия виртуальных функций. Обычные функции в Java эквивалентны виртуальным функциям C++, а динамическое связывание является поведением по умолчанию в Java. Если вы не хотите, чтобы функция обладала характеристиками виртуальной функции в Java, можно добавить ключевое слово final, чтобы сделать её невиртуальной функцией.
Переопределение
Мы расскажем, как поведение переопределённых методов влияет на полиморфизм при проектировании классов в Java.
Мы уже обсуждали переопределение методов, то есть подклассы могут переопределять методы родительского класса.
Когда объект подкласса вызывает переопределённый метод, он вызывает метод подкласса, а не переопределённый метод в родительском классе.
Чтобы вызвать переопределённый метод в родительском классе, необходимо использовать ключевое словоsuper。
Код файла Employee.java:
Предположим, что следующий класс наследует класс Employee:
Код файла Salary.java:
Теперь давайте внимательно прочитаем следующий код и попробуем определить результат его вывода:
Код файла VirtualDemo.java:
Результат компиляции и выполнения приведенного выше примера выглядит следующим образом:
Employee 构造函数 Employee 构造函数 使用 Salary 的引用调用 mailCheck -- Salary 类的 mailCheck 方法 邮寄支票给:员工 A ,工资为:3600.0 使用 Employee 的引用调用 mailCheck-- Salary 类的 mailCheck 方法 邮寄支票给:员工 B ,工资为:2400.0
Разбор примера
-
В примере создаются два объекта Salary: один с использованием ссылки Salary s, а другой — с использованием ссылки Employee e.
-
При вызове s.mailCheck() компилятор на этапе компиляции находит mailCheck() в классе Salary, а во время выполнения JVM вызывает mailCheck() класса Salary.
-
e — это ссылка на Employee, но ссылка e в итоге вызывает метод mailCheck() класса Salary.
-
Во время компиляции компилятор использует метод mailCheck() в классе Employee для проверки оператора, но во время выполнения виртуальная машина Java (JVM) вызывает метод mailCheck() в классе Salary.
Весь описанный выше процесс называется вызовом виртуального метода, а сам метод — виртуальным методом.
Все методы в Java могут вести себя таким образом. Поэтому переопределённые методы могут вызываться во время выполнения независимо от того, какой тип данных имеет ссылочная переменная в исходном коде на этапе компиляции.
Способы реализации полиморфизма
Способ 1: Переопределение:
Этот материал уже подробно рассматривался в предыдущей главе, поэтому дополнительных пояснений не даётся. Подробнее см.:Переопределение и перегрузка в Java。Способ 2: Интерфейсы
1. Самый наглядный пример интерфейса в жизни — розетка. Например, вилку с тремя штырьками можно вставить в розетку с тремя отверстиями, потому что в каждой стране свои правила интерфейса. За границей это может не работать, потому что в других странах определяют свои типы интерфейсов.
2. Интерфейс в Java похож на интерфейс в жизни; это набор сигнатур методов, но без реализаций методов. Подробнее см.Интерфейсы в Javaв этой главе.
Способ 3: Абстрактные классы и абстрактные методы
Подробнее см. в главеАбстрактные классы Java.
Другие расширения