На какой объект будет реально указывать ссылка во время выполнения, не всегда можно точно определить на этапе компиляции. Полиморфизм позволяет ссылке указывать на объекты разных типов в разное время во время выполнения. Ссылка супертипа демонстрирует полиморфное поведение, поскольку она может указывать на объекты своих подтипов.
Когда у объекта вызывается He-private
-метод экземпляра, то реально выполняемое описание метода определяется одновременно и типом объекта во время выполнения, и сигнатурой метода. Динамический поиск метода — это основанный на типе объекта процесс определения того, какое описание метода обозначается данной сигнатурой метода во время выполнения. Однако вызов private
-метода экземпляра не является полиморфным, поскольку вызов может произойти только внутри класса и ограничивается реализацией private
-метода во время компиляции.
Иерархия наследования, изображенная на рис. 6.5, реализована в примере 6.14. Реализация метода draw()
переопределена во всех подклассах класса Shape
. Вызов метода draw()
в двух циклах в строках (3) и (4) в примере 6.14 основывается на полиморфном поведении ссылок и динамическом поиске метода. В массиве shapes
содержатся ссылки типа Shape
(Фигура), обозначающие Circle
(Окружность), Rectangle
(Прямоугольник) и Square
(Квадрат), как показано в строке (1). Во время выполнения динамический поиск находит реализацию метода draw()
, которую надо выполнить на основании типа объектов, на которые указывают элементы массива. Такая же схема применяется и для случая с массивом drawables
в строке (2), который содержит ссылки типа IDrawable
, а им можно присвоить любой объект класса, который реализует интерфейс IDrawable
. Первый цикл будет продолжать работать без изменений, если объекты нового подкласса класса Shape
добавить в массив shapes
. Если они не переопределяют метод draw()
, будет выполнена унаследованная версия метода. Такое полиморфное поведение применимо к массиву drawables
, в котором объекты подтипа с гарантией реализуют интерфейс IDrawable
.
Полиморфизм и динамический поиск метода образуют мощную парадигму программирования, которая упрощает определения клиентов, содействует разделению объектов и поддерживает динамическую перенастройку связей между объектами во время выполнения.
interface IDrawable {
void draw();
}
class Shape implements IDrawable {
public void draw() { System.out.println("Drawing a Shape."); }
}
class Circle extends Shape {
public void draw() { System.out.println("Drawing a Circle."); }
}
class Rectangle extends Shape {
public void draw() { System.out.println("Drawing a Rectangle."); }
}
class Square extends Rectangle {
public void draw() { System.out.println("Drawing a Square."); }
}
class Map implements IDrawable {
public void draw() { System.out.println("Drawing a Map."); }
}
public class PolymorphRefs {
public static void main(String[] args) {
Shape[] shapes = { new Circle(), new Rectangle(), new Square() }; // (1)
IDrawable[] drawables = { new Shape(), new Rectangle(), new Map() };// (2)
System.out.println("Draw shapes:");
for (int i = 0; i < shapes.length; i++) // (3)
shapes[i].draw();
System.out.println("Draw drawables:");
for (int i = 0; i < drawables.length; i++) // (4)
drawables[i].draw();
}
}
Вывод программы:
Draw shapes:
Drawing a Circle.
Drawing a Rectangle.
Drawing a Square.
Draw drawables:
Drawing a Shape.
Drawing a Rectangle.
Drawing a Map.
Преобразование типов значений ссылок | Наследование в сравнении с агрегацией |