В предлагаемом материале рассказывается об абстрактных классах и методах, об интерфейсах и операторе instanceof.
Абстрактные методы
PHP 5
поддерживает объявление абстрактных методов, то есть таких методов, которые только объявляются, но не определяются (не имеют тела).
abstract public function foo();
Как видим, для объявления абстрактного метода используется ключевое слово abstract, а само объявление обрывается точкой с запятой после названия метода с последующими круглыми скобками (возможно, с параметрами). Блок, заключенный в фигурные скобки (тело метода), отсутствует.
Абстрактные
методы, объявленные в родительском классе, должны быть обязательно перекрыты обычными (не абстрактными) методами в одном из классов-наследников. При этом перекрывающий метод не может иметь видимость более ограниченную, чем исходный абстрактный метод.
Смысл объявления абстрактных методов заключается в том, что они гарантируют наличие определенной функциональности в классах-наследниках, но «откладывают» непосредственную реализацию этой функциональности до разработки этих
классов.
Абстрактные классы
Если хотя бы один метод класса объявлен абстрактным, то и весь класс тоже должен быть объявлен абстрактным. Делается это с помощью все того же ключевого слова abstract.
abstract class Foo { /* ... */ }
Создать объект абстрактного класса невозможно. Попытка сделать это вызовет фатальную
ошибку.
$foo = new Foo;
Fatal error: Cannot instantiate abstract class Foo
Поэтому абстрактный класс должен быть сначала унаследован, а его абстрактные методы должны быть перекрыты в классе-наследнике (см. «Абстрактные методы»).
Наряду с объявлениями абстрактных методов, абстрактный класс может содержать и определения обычных методов.
Интерфейсы
Еще одна возможность объявить методы, не определяя их, появилась в PHP 5 благодаря поддержке интерфейсов. Интерфейсы в определенной степени напоминают абстрактные классы (см. «Оператор instanceof»), но могут содержать только объявления методов (без их определения). Поскольку эти методы
находятся внутри интерфейса, то использовать для их объявления ключевое слово abstract не нужно. Другой особенностью является то, что все эти методы должны быть публичными. Для объявления же самого интерфейса используется ключевое слово interface.
<?php
interface FooInterface
{
public function foo($bar);
}
?>
Интерфейсы могут быть в дальнейшем применены классами с помощью ключевого слова implements. Это значит, что класс должен объявить и определить все методы, содержащиеся в интерфейсе.
<?php
class Foo implements FooInterface
{
public function foo($bar)
{
print $bar;
}
}
?>
Применение интерфейса классом сродни наследованию (см. «Оператор instanceof»). Однако, если родительский класс может быть только один, то количество приненяемых интерфейсов не ограничено[7]. Тем самым частично компенсируется отсутствие поддержки множественного наследования.
Замечание
Однако, применяя несколько интерфейсов одновременно, следует убедиться в отсутствии у них методов с совпадающими названиями.
Оператор
instanceof
Проверить принадлежность данного объекта к тому или иному классу можно с помощью оператора instanceof, который, в зависимости от результата проверки, возвращает логическую величину true или false. При этом объект принадлежит не только непосредственно тому классу, от которого он был образован, но и его родительским классам.
class Foo { /* ... */ }
class Bar extends Foo { /* ... */ }
$bar = new Bar;
var_dump($bar instanceof Foo);
bool(true)
С помощью оператора instanceof можно проверять не только принадлежность объектов к определенным классам, но и применение классами, к которым принадлежит объект, определенных интерфейсов.
Оператор instanceof был введен в PHP 5 и заменил собой устаревшую функцию is_a(). С целью обратной совместимости она все еще поддерживается, но использовать ее больше не рекомендуется.
Контрольные вопросы и задания
Найдите
и исправьте ошибку.
<?php
abstract class Foo
{
abstract public function printFoo($foo);
}
class Bar extends Foo
{
public function printBar($bar)
{
print $bar;
}
}
?>
Разработайте класс Foo, применяющий интерфейс FooInterface.
<?php
interface FooInterface
{
public function printFoo($foo);
}
?>
Предложите способ условного исполнения кода в том лишь случае, если объект $obj применяет интерфейс SomeInterface.