Вводный курс. Язык программирования Java
- Вводный курс. Язык программирования Java
- Просмотров: 4114
19, Практика. Полиморфизм
Рассмотрим пример с геометрическими фигурами. Имеется базовый класс c именем Figura и несколько производных классов: окружность (тип Circle), прямоугольник (тип Rect) и трапеция (тип Trap). Необходимо определить площадь каждой фигуры и вывести эти значения на печать.
Вот листинг классов.
public class Figura {
public double Area (){
return 0;
}
public void PrintArea(){}
}
Обратите внимание, класс не имеет явно записанного конструктора. Компилятор будет использовать конструктор по умолчанию.
Класс содержит два пустых метода Area() и PrintArea(), которые в данном классе совершенно ничего не делают, но их наличие крайне важно: именно через них будет в последующем обеспечен полиморфизм.
public class Circle extends Figura{
int a;
public Circle (int A)
{
a=A;
}
public double Area (){
return Math.PI*a*a;
}
public void PrintArea(){
System.out.println("Площадь круга: "+ Area());
}
}
Класс Circle является производным от класса Figura, на это указывает ключевое слово extends. Данный класс содержит конструктор public Circle (int A), методы Area() и PrintArea(), которые переопределены в Circle (имя метода как у родителя, а в внутри каждого метода записан другой программный код).
Выполним создание объекта класса Circle, следующим образом:
Figura f = new Circle(1);
Первое впечатление - это ошибка. Мы видим присвоение между переменными разного типа (тип Figura и тип Circle). Но это не так. Операция допустима, поскольку тип Circle (окружность) является типом Figura посредством наследования.
Все ссылки на объекты производных классов совместимы по типу с ссылками на объекты базового класса.
Выполним метод Area ()
f.Area ();
Какой метод Area() будет вызван: из класса Figura или класса Circle?
При выполнении данного оператора работает механизм динамического или позднего связывания. На данном этапе выполнения программы уже известно, что был создан объект типа Circle и ссылка на этот объект была присвоена переменной f. Следовательно, будет вызван метод Area() класса Circle. Так происходит автоматический выбор нужного метода для исполнения.
Продолжим листинг классов.
//класс прямоугольник
public class Rect extends Figura {
int a;
int b;
public Rect (int A, int B)
{
a=A;
b=B;
}
public double Area (){
return a*b;
}
public void PrintArea(){
System.out.println("Площадь прямоугольника: "+ Area());
}
}
//класс трапеция
public class Trap extends Figura{
int a;
int b;
int h;
public Trap (int A, int B, int H)
{
a=A;
b=B;
h=H;
}
public double Area (){
return (a + b)*h/2;
}
public void PrintArea(){
System.out.println("Площадь трапеции: "+ Area());
}
}
Метод main()
public static void main(String[] args) {
//создаем массив ссылок на базовый класс
Figura [] f = new Figura [5];
//создаем объекты, ссылки на объеты храним
//в массиве ссылок базового класса
f[0]= new Circle(1);
f[1]= new Rect(1,1);
f[2]= new Trap(1,1,1);
f[3]= new Circle(1);
f[4]= new Rect(1,1);
//работает механизм полимофизма
for(int i=0; i<f.length; i++)
f[i].PrintArea();
}
Результат работы:
Площадь круга: 3.141592653589793
Площадь прямоугольника: 1.0
Площадь трапеции: 1.0
Площадь круга: 3.141592653589793
Площадь прямоугольника: 1.0
Полиморфизм проявляется строке
f[i].PrintArea();
где один и тот же метод используется для вычисления площади разных фигур (окрухность Circle, прямоугольник Rect и трапеция Trap).