PHP tiene clases, métodos y propiedades abstractas.
Las clases definidas como abstractas no pueden ser
instanciadas, y cualquier clase que contenga al menos un
método abstracto debe ser también abstracta.
Los métodos definidos como abstractos se contentan con declarar la firma del método y con indicar si es público o protegido;
no pueden definir la implementación. Las propiedades definidas como abstractas
pueden declarar un requisito para el comportamiento de get
o de set
,
y pueden proporcionar una implementación para una de estas operaciones, pero no para ambas.
Al heredar de una clase abstracta, todos los métodos marcados como abstractos en la declaración de la clase padre deben ser definidos por la clase hija y seguir las reglas habituales de herencia y de compatibilidad de firma.
A partir de PHP 8.4, una clase abstracta puede declarar una propiedad abstracta, pública o protegida. Una propiedad abstracta protegida puede ser satisfecha por una propiedad accesible en lectura/escritura desde un contexto protegido o público.
Una propiedad abstracta puede ser satisfecha ya sea por una propiedad estándar, ya sea por una propiedad con hooks definidos, correspondiente a la operación requerida.
Ejemplo #1 Ejemplo de método abstracto
<?php
abstract class AbstractClass
{
// Fuerza a las clases hijas a definir este método
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// método común
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";
?>
El resultado del ejemplo sería:
ConcreteClass1 FOO_ConcreteClass1 ConcreteClass2 FOO_ConcreteClass2
Ejemplo #2 Ejemplo de método abstracto
<?php
abstract class AbstractClass
{
// Un método abstracto solo debe definir los argumentos requeridos
abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
// Una clase hija puede definir argumentos opcionales que no están presentes en la firma del padre
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";
?>
El resultado del ejemplo sería:
Mr. Pacman Mrs. Pacwoman
Ejemplo #3 Ejemplo de propiedad abstracta
<?php
abstract class A
{
// Las clases derivadas deben tener una propiedad públicamente accesible en lectura.
abstract public string $readable {
get;
}
// Las clases derivadas deben tener una propiedad modificable en escritura, protegida o pública.
abstract protected string $writeable {
set;
}
// Las clases derivadas deben tener una propiedad simétrica protegida o pública.
abstract protected string $both {
get;
set;
}
}
class C extends A
{
// Esto satisface el requisito y también hace que la propiedad sea modificable, lo cual es válido.
public string $readable;
// Esto NO satisfaría el requisito, ya que la propiedad no es públicamente accesible en lectura.
protected string $readable;
// Esto satisface exactamente el requisito, por lo que es suficiente.
// La propiedad solo puede ser modificada desde un contexto protegido.
protected string $writeable {
set => $value;
}
// Esto amplía la visibilidad de protegido a público, lo cual es aceptable.
public string $both;
}
?>
Una propiedad abstracta en una clase abstracta puede proporcionar implementaciones para cualquier punto de anclaje,
pero debe tener get
o set
declarados pero no definidos (como en el ejemplo anterior).
Ejemplo #4 Ejemplo de propiedad abstracta con hooks
<?php
abstract class A
{
// Esto proporciona una implementación por defecto (pero sustituible) para set,
// y exige que las clases derivadas proporcionen una implementación para get.
abstract public string $foo {
get;
set {
$this->foo = $value
};
}
}
?>