PHP поддерживает абстрактные классы, методы и свойства. Нельзя создавать экземпляры абстрактных классов, и класс, в котором объявили хотя бы один абстрактный метод или свойство, должен быть абстрактным. Абстрактные методы объявляют только сигнатуру и открытую или защищённую область видимости метода; абстрактным методам нельзя определять реализацию.
При наследовании абстрактного класса дочерний класс обязан определить методы, которые пометили абстрактными в объявлении родительского класса, и следовать обычным правилам наследования и совместимости сигнатуры.
Начиная с PHP 8.4 в абстрактных классах разрешили объявлять абстрактные свойства, как с открытой, так и с защищённой областью видимости. Защищённому абстрактному свойству удовлетворяет свойство, которое доступно для чтения или записи как из защищённой, так и из открытой области видимости.
Абстрактному свойству удовлетворяет либо стандартное свойство, либо свойство, для которого определили хуки, которые соответствуют операции чтения или записи абстрактного свойства.
Пример #1 Пример абстрактного метода
<?php
abstract class AbstractClass
{
// Эти методы потребуется определить в дочернем классе
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// Общий метод
public function printOut()
{
print $this->getValue() . "\n";
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue()
{
return "ConcreteClass1";
}
public function prefixValue($prefix)
{
return "{$prefix}ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue()
{
return "ConcreteClass2";
}
public function prefixValue($prefix)
{
return "{$prefix}ConcreteClass2";
}
}
$class1 = new ConcreteClass1();
$class1->printOut();
echo $class1->prefixValue('FOO_'), "\n";
$class2 = new ConcreteClass2();
$class2->printOut();
echo $class2->prefixValue('FOO_'), "\n";
?>
Результат выполнения приведённого примера:
ConcreteClass1 FOO_ConcreteClass1 ConcreteClass2 FOO_ConcreteClass2
Пример #2 Пример абстрактного метода
<?php
abstract class AbstractClass
{
// Абстрактному методу необходимо только определить обязательные аргументы
abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
// Дочернему классу разрешается определять в сигнатуре метода необязательные параметры,
// которые не объявляли в сигнатуре метода родительского класса
public function prefixName($name, $separator = ".")
{
if ($name == "Pacman") {
$prefix = "Mr";
} elseif ($name == "Pacwoman") {
$prefix = "Mrs";
} else {
$prefix = "";
}
return "{$prefix}{$separator} {$name}";
}
}
$class = new ConcreteClass();
echo $class->prefixName("Pacman"), "\n";
echo $class->prefixName("Pacwoman"), "\n";
?>
Результат выполнения приведённого примера:
Mr. Pacman Mrs. Pacwoman
Пример #3 Пример абстрактного свойства
<?php
abstract class A
{
// В дочернем классе потребуется объявить открытое для чтения свойство
abstract public string $readable {
get;
}
// В дочернем классе потребуется объявить защищённое или открытое для записи свойство
abstract protected string $writeable {
set;
}
// В дочернем классе потребуется объявить защищённое или открытое свойство с симметричной областью видимости
abstract protected string $both {
get;
set;
}
}
class C extends A
{
// Определение удовлетворяет требованию абстрактного свойства, и делает свойство доступным для записи, что допустимо
public string $readable;
// Такое определение того же свойства НЕ удовлетворит требованию,
// поскольку свойство недоступно для открытого чтения
protected string $readable;
// Определение на 100 % удовлетворяет требованию абстракции, поэтому такого определения достаточно.
// Свойство доступно для записи и только из защищённой области видимости
protected string $writeable {
set => $value;
}
// Определение расширяет видимость с защищенной до общедоступной, это допустимо
public string $both;
}
?>
Абстрактное свойство абстрактного класса должно содержать объявление по крайней мере одного абстрактного хука.
При объявлении для абстрактного свойства и хука get
, и хука set
одному хуку в абстрактном классе разрешается предоставить реализацию, как в приведённом примере.
Пример #4 Пример абстрактного свойства
<?php
abstract class A
{
// Определение стандартной, но переопределяемой реализации хука set,
// и требование к дочерним классам предоставить реализацию хука get
abstract public string $foo {
get;
set {
$this->foo = $value
};
}
}
?>