Herencia de Objetos
La herencia es un principio de programación bien establecido y PHP hace uso
de él en su modelado de objetos. Este principio afectará la manera
en que muchas clases y objetos se relacionan unas con otras.
Por ejemplo, cuando se extiende una clase, la subclase hereda todos los
métodos públicos y protegidos de la clase padre. A menos que una clase sobrescriba
esos métodos, mantendrán su funcionalidad original.
Esto es útil para la definición y abstracción de la funcionalidad y permite la
implementación de funcionalidad adicional en objetos similares sin la
necesidad de reimplementar toda la funcionalidad compartida.
Los métodos privados de una clase padre no son accesibles para una clase hija. Como resultado,
las clases hijas pueden reimplementar un método privado sin tener en cuenta las reglas de
herencia normales. Antes de PHP 8.0.0, sin embargo, se aplicaban las restricciones final
y static
a los métodos privados. A partir de PHP 8.0.0, la única restricción de métodos privados
es private final
que se aplica en el constructor de la clase, ya que
es una forma común de "deshabilitar" el constructor cuando es usado en métodos estáticos de fábrica (Patrón Factory).
La visibilidad
de los métodos, propiedades y constantes pueden ser relajarse, por ejemplo,
un méetodo protected
puede marcase como
public
, pero no pueden restringirse, por ejemplo.
marcando una propiedad public
como private
.
Nota:
A menos que la carga automática sea utilizada, entonces las clases deben ser definidas antes de ser
usadas. Si una clase se extiende a otra, entonces la clase padre debe ser declarada
antes de la estructura de clase hija. Esta regla se aplica a las clases que heredan
de otras clases e interfaces.
Nota:
No está permitido sobrescribir una propiedad de lectura-escritura con una propiedad de sólo lectura o viceversa.
<?php
class A {
public int $prop;
}
class B extends A {
// Ilegal: lectura-escritura -> sólo lectura
public readonly int $prop;
}
?>
Ejemplo #1 Ejemplo de herencia
<?php
class Foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}
public function printPHP()
{
echo 'PHP is great.' . PHP_EOL;
}
}
class bar extends Foo
{
public function printItem($string)
{
echo 'Bar: ' . $string . PHP_EOL;
}
}
$foo = new Foo();
$bar = new Bar();
$foo->printItem('baz'); // Salida: 'Foo: baz'
$foo->printPHP(); // Salida: 'PHP is great'
$bar->printItem('baz'); // Salida: 'Bar: baz'
$bar->printPHP(); // Salida: 'PHP is great'
?>
Return Type Compatibility with Internal Classes
Prior to PHP 8.1, most internal classes or methods didn't declare their return types,
and any return type was allowed when extending them.
As of PHP 8.1.0, most internal methods started to "tentatively" declare their return type,
in that case the return type of methods should be compatible with the parent being extended;
otherwise, a deprecation notice is emitted.
Note that lack of an explicit return declaration is also considered a signature mismatch,
and thus results in the deprecation notice.
If the return type cannot be declared for an overriding method due to PHP cross-version compatibility concerns,
a #[ReturnTypeWillChange]
attribute can be added to silence the deprecation notice.
Ejemplo #2 The overriding method does not declare any return type
<?php
class MyDateTime extends DateTime
{
public function modify(string $modifier) { return false; }
}
// "Deprecated: Return type of MyDateTime::modify(string $modifier) should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice" as of PHP 8.1.0
?>
Ejemplo #3 The overriding method declares a wrong return type
<?php
class MyDateTime extends DateTime
{
public function modify(string $modifier): ?DateTime { return null; }
}
// "Deprecated: Return type of MyDateTime::modify(string $modifier): ?DateTime should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice" as of PHP 8.1.0
?>
Ejemplo #4 The overriding method declares a wrong return type without a deprecation notice
<?php
class MyDateTime extends DateTime
{
/**
* @return DateTime|false
*/
#[ReturnTypeWillChange]
public function modify(string $modifier) { return false; }
}
// No notice is triggered
?>