Una clase abstracta de PHP se declara con abstract class Name y no se puede crear con new. Es una base para otras clases: puede tener propiedades, un constructor y métodos terminados, además de métodos abstract sin cuerpo, que cada clase hija debe implementar.
describe() se escribe una vez en Shape y llama a area(), que aporta cada hija. La clase abstracta garantiza que el método existe, así que describe() puede contar con él.
No puedes crear una clase abstracta con new
Una clase abstracta está incompleta a propósito: Shape::area() no tiene cuerpo, así que un objeto Shape a secas no tendría nada que ejecutar. PHP se niega a crear uno y lanza un Error:
Métodos abstractos: las reglas
Un método abstracto tiene una firma y un punto y coma en lugar de cuerpo. Cada hija debe implementarlo con una firma compatible y la misma visibilidad o una más amplia: un método abstract protected puede ser protected o public en la hija, nunca private. Una clase con un solo método abstracto ya debe declararse abstracta.
Una hija que se salta un método abstracto detiene el script antes de que se ejecute nada, salvo que la hija también se declare abstracta y deje el método a sus propias hijas:
PHP Fatal error: Class Square contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Shape::area) in /home/index.php on line 3
El patrón template method
El motivo más habitual para escribir una clase abstracta: una secuencia fija de pasos en la que unos pocos cambian. La clase base es dueña de la secuencia en un método final, y las hijas rellenan los pasos. Aquí el mismo informe se genera como texto plano y como tabla HTML:
Ejecútalo y la pestaña Página muestra la tabla HTML encima de la versión en texto plano. open() y close() tienen cuerpos por defecto, así que solo HtmlReport se molesta en sobrescribirlos; row() es abstracto porque no hay un valor por defecto razonable. Hacer render() final impide que una hija cambie el orden de los pasos.
Una clase abstracta puede implementar una interfaz
Una clase abstracta puede declarar implements y dejar algunos de los métodos de la interfaz para sus hijas. Es la forma estándar de emparejar una interfaz (el tipo) con una clase base (el código compartido):
El código usa la interfaz Cache como declaración de tipo, así que una clase que no puede extender BaseCache (porque ya extiende otra cosa) puede seguir implementando Cache directamente.
Cuándo usar una clase abstracta y cuándo no
Recurre a una clase abstracta cuando las clases de una familia comparten código real: propiedades, un constructor, métodos iguales para todas. Si la base no contuviera más que métodos abstractos, sería una interfaz disfrazada, y una interfaz es la mejor opción porque una clase puede implementar muchas interfaces pero extender solo una clase. Si solo quieres compartir unos cuantos métodos auxiliares entre clases no relacionadas, usa un trait en lugar de forzarlas bajo un mismo padre.
Una prueba rápida antes de escribir abstract class: ¿cada hija sería realmente un tipo de la base (Circle es un Shape)? Si la respuesta sincera es "puede hacer esto" y no "es uno de estos", escribe una interfaz.
Preguntas frecuentes
¿Qué es una clase abstracta en PHP?
Una clase declarada con abstract class Name que no se puede crear con new. Es una base para otras clases: puede contener propiedades, un constructor y métodos normales, y puede declarar métodos abstract que cada clase hija debe implementar.
¿Qué es un método abstracto en PHP?
Un método declarado con abstract y sin cuerpo: abstract protected function render(array $rows): string;. Una clase que contiene uno debe declararse a su vez abstract, y cada clase hija no abstracta debe definir un método con una firma compatible.
¿Una clase abstracta puede tener constructor en PHP?
Sí. No puedes llamar a new sobre la clase abstracta, pero su constructor se ejecuta cuando se crea una clase hija, ya sea automáticamente (si la hija no tiene constructor) o mediante parent::__construct(...).
¿Se puede instanciar una clase abstracta en PHP?
No. new Shape() sobre una clase abstracta lanza un Error: Cannot instantiate abstract class Shape. Crea en su lugar un objeto de una clase hija concreta, por ejemplo new Circle(2).
¿Cuándo debo usar una clase abstracta en PHP?
Cuando varias clases relacionadas comparten código real (propiedades, un constructor, métodos comunes) y se diferencian en unos pocos pasos. Pon el código compartido en la clase abstracta y declara abstractos los pasos que cambian. Si no hay código compartido y solo necesitas un contrato, usa una interfaz.