Полиморфизм (многоформенность) является следствием идеи наследования. В общих словах, полиморфность класса — это свойство базового класса использовать функции производных классов, даже если на момент определения еще неизвестно, какой именно класс будет включать его в качестве базового и, тем самым, становиться от него производным.
Рассмотрим свойство полиморфности классов на основе следующего примера:
<?php class A { // Выводит, функция какого класса была вызвана function Test() { echo "Test from A\n"; } // Тестовая функция — просто переадресует на Test() function Call() { Test(); } } class B extends A { // Функция Test() для класса B function Test() { echo "Test from B\n"; } } $a=new A(); $b=new B(); ?>
Используем следующие следующие команды:
$a->Call(); // выводит "Test from A" $b->Test(); // выводит "Test from B" $b->Call(); // Внимание! Выводит "Test from B"!
Обратите внимание на последнюю строчку: вопреки ожиданиям, вызывается не функция Test() из класса A, а функция из класса B! Складывается впечатление, что Test() из B просто переопределила функцию Test() из A. Так оно на самом деле и есть. Функция, переопределяемая в производном классе, называется виртуальной.
Механизм виртуальных функций позволяет, например, "подсовывать" функциям, ожидающим объект одного класса, объект другого, производного, класса. Еще один классический пример — класс, воплощающий собой свойства геометрической фигуры, и несколько производных от него классов — квадрат, круг, треугольник и т. д.
Базовый класс имеет виртуальную функцию Draw(), которая заставляет объект нарисовать самого себя. Все производные классы-фигуры, разумеется, переопределяют эту функцию (ведь каждую фигуру нужно рисовать по-особому). Также у нас есть массив фигур, причем мы не знаем, каких именно. Зато, используя полиморфизм, мы можем, не задумываясь, перебрать все элементы массива и вызвать для каждого из них метод Draw() — фигура сама "решит", какого она типа и как ее рисовать.
А вот еще один практический пример, показывающий свойство класса - полиморфизм:
<?php class Base { function funct() { echo "<h2>Функция базового класса</h2>"; } function base_funct() { $this->funct(); } } class Derivative extends Base { function funct() { echo "<h3>Функция производного класса</h3>"; } } $b = new Base(); $d = new Derivative(); $b->base_funct(); $d->funct(); $d->base_funct(); // Скрипт выводит: // Функция базового класса // Функция производного класса // Функция производного класса ?>
В рассмотренном примере функция base_funct() класса Base была перезаписана одноименной функцией класса Derivative.