Проверка совместимости типов производится во время выполнения программы, а не во время ее трансляции. Для этого применяется новый оператор instanceof.
<?php ## Оператор instanceof.
$obj=new Circle(5);
if (!($obj instanceof Circle))
die("Argument must be an instance of Circle.<br>");
$obj->show();
?>
C помощью instanceof допустимо использовать также имя класса, заданное неявно (в переменной).
1. Расширить класс Message(из задания в Лекции №12),создав классPrivateMessage. Переопределить метод show() класса Message так, чтобы для объектов класса PrivateMessageони отображались только у того пользователя, которому адресовалось сообщение.
2. Сделать класс Message абстрактным и расширить его классами PrivateMessageиPublicMessage.
До сих пор мы подразумевали, что у каждого производного класса может быть только единственный базовый. Наследовать свойства и методы сразу нескольких классов (например, писать class a extends в, с, d) в РНР нельзя.
Взамен множественного наследования пришел другой, упрощенный метод: использование интерфейсов. Интерфейс (interface) представляет собой обычный абстрактный класс, но только в нем не может быть свойств, и тела у всех методов не определены. Фактически некоторый интерфейс указывает лишь список методов, их аргументы и модификаторы доступа (обычно только protected и public). Допускается также описание констант внутри интерфейса с помощью ключевого слова const.
Класс, наследующий некоторый интерфейс обязан содержать в себе определения всех методов, объявленных в интерфейсе. Если хотя бы один из методов не будет реализован, вы не сможете создать объект класса: возникнет ошибка. Поэтому принято называть не класс, наследующий интерфейс, а класс, реализующий интерфейс.
Главное достоинство заключается в том, что класс может реализовывать сразу несколько интерфейсов. Для связи класса с интерфейсом используется ключевое слово implements:
interface Shape {
public function show(); // тело не указывается!
}
interface Movement {
public function move (); // вращает объект
//класс Circle реализует интерфейсы Shape и Movement
class Circle implements Shape, Movement {
public function show () { ... }
public function move () { ... }
}
Интерфейсы в свою очередь могут также наследовать (расширять) друг друга. При расширении интерфейсов нужно использовать ключевое слово extends, а не implements.
<?php ## Множественное наследование интерфейсов.
// Сущность: "материальный объект",
interface IWorldObject {
public function getCoord(); // возвращает координаты объекта
}
interface IWheeled {
public function getNumWheels(); // возвращает число колес
public function getNumPassengers(); // максимальное число пассажиров
}
//класс Audi реализует все три интерфейса, описанных выше
class Audi implements ITransport, IWheeled, IWorldObject {
private $coordArray;
public function getCoord() { return $coordArray; }
public function getNumWheels() { return 4; }
public function getNumPassengers() { return 5; }
}
?>
Интерфейс IWorldObjectрасширяется интерфейсом ITransport, который, в свою очередь, реализуется классом Audi. В то же время, Audiреализует IWorldObjectи напрямую. Получается, что у Audi имеются две реализации интерфейса "материальный объект": непосредственный и через "транспортное средство". Такая ситуация довольно типична и является совершенно корректной: если некоторый интерфейс реализуется дважды, то в действительности в классе имеется лишь одна "ссылка" на него. Таким образом, никакого конфликта нет.