Herança de Objetos
Herança é um conceito de programação estabelecido, e o PHP faz
uso deste em seu modelo de objetos. Este princípio afeta a forma
com que classes e objetos se relacionam com outras.
Por exemplo, ao estender uma classe, a subclasse herda todos os métodos
públicos e protegidos, propriedades e constantes da classe pai.
A não que uma classe sobrescreva
estes métodos, eles manterão sua funcionalidade original.
Isto é útil para definir uma funcionalidade abstrata, e permitir a
implementação de uma funcionalidade adicional em objetos similares sem a
necessidade de reimplementar todas as funcionalidades compartilhadas.
Os métodos privados de uma classe pai não são acessíveis a uma classe filha. Como resultado,
as classes filhas podem reimplementar um método privado sem levar em conta as regras normais
de herança. Antes do PHP 8.0.0, entretanto, as restrições final e static
eram aplicadas aos métodos privados. Desde o PHP 8.0.0, a única restrição de método privado
que é aplicada é private final para construtores, já que essa
é uma maneira comum de "desabilitar" o construtor ao usar métodos de fábrica estáticos.
A visibilidade
de métodos, propriedades e constantes pode ser relaxada, por exemplo, um
método com protected pode ser marcado como
public, mas não pode ser restrito, por exemplo,
marcar uma propriedade que tenha public como private.
Uma exceção são os construtores, cuja visibilidade pode ser restrita, ou seja,
um construtor public pode ser declarado como private
numa classe filha.
Nota:
A não ser que o autoload seja usado, as classes devem ser definidas antes de
utilizadas. Se uma classe estende outra, a classe pai deve ser declarada
antes da estrutura da classe filha. Esta regra se aplica a classes que herdam
outras classes e interfaces.
Nota:
Não é permitido sobrescrever uma propriedade de leitura/gravação com um propriedade somente de leitura ou vice-versa.
Exemplo #1 Exemplo de Herança
<?php
class Foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}
public function printPHP()
{
echo 'PHP é ótimo' . PHP_EOL;
}
}
class Bar extends Foo
{
public function printItem($string)
{
echo 'Bar: ' . $string . PHP_EOL;
}
}
$foo = new Foo();
$bar = new Bar();
$foo->printItem('baz'); // Saída: 'Foo: baz'
$foo->printPHP(); // Saída: 'PHP é ótimo'
$bar->printItem('baz'); // Saída: 'Bar: baz'
$bar->printPHP(); // Saída: 'PHP é ótimo'
?>
Compatibilidade de Tipo de Retorno com Classes Internas
Antes do PHP 8.1, a maioria das classes ou métodos internos não declaravam seus tipos de retorno,
e qualquer tipo de retorno era permitido ao estendê-los.
A partir do PHP 8.1.0, a maioria dos métodos internos começaram a declarar seu tipo de retorno de forma "experimental",
nesse caso o tipo de retorno dos métodos deve ser compatível com o pai sendo estendido,
do contrário, um aviso de descontinuação é emitido.
Note que a ausência de uma declaração de retorno explícita também é considerada uma incompatibilidade de assinatura
e, portanto, resulta no aviso de descontinuação.
Se o tipo de retorno não puder ser declarado para um método que sobrepõe devido à preocupações com compatibilidade entre versões PHP,
um atributo ReturnTypeWillChange pode ser adicionado para silenciar o aviso de descontinuação.
Exemplo #2 O método que sobrepõe não declara nenhum tipo de retorno
<?php
class MeuDateTime extends DateTime
{
public function modify(string $modifier) { return false; }
}
// "Deprecated: Return type of MeuDateTime::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" a partir do PHP 8.1.0
?>
Exemplo #3 O método que sobrepõe declara um tipo de retorno errado
<?php
class MeuDateTime extends DateTime
{
public function modify(string $modifier): ?DateTime { return null; }
}
// "Deprecated: Return type of MeuDateTime::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" a partir do PHP 8.1.0
?>
Exemplo #4 O método que sobrepõe declara um tipo de retorno errado sem um aviso de descontinuação
<?php
class MeuDateTime extends DateTime
{
/**
* @return DateTime|false
*/
#[\ReturnTypeWillChange]
public function modify(string $modifier) { return false; }
}
// Nenhum aviso é emitido
?>