Aplicando o Princípio da Substituição de Liskov em PHP
- #PHP
O Que é o Princípio de Liskov?
Imagine que você tem uma classe Animal
e duas subclasses: Cachorro
e Gato
. O Princípio de Substituição de Liskov (LSP) diz que você deve ser capaz de substituir a classe Animal
por qualquer uma de suas subclasses (como Cachorro
ou Gato
) sem causar problemas no comportamento do sistema.
Ou seja, se você usar um Cachorro
no lugar de um Animal
, o sistema não deve quebrar ou se comportar de forma inesperada. O mesmo vale para o Gato
.
Exemplo de Código PHP
Código sem o Princípio de Liskov (violando LSP)
Imagina que temos uma classe Animal
, e duas subclasses Cachorro
e Pato
. O código a seguir pode funcionar de forma inesperada:
php
CopiarEditar
<?php
class Animal {
public function fazerSom() {
echo "O animal faz um som";
}
}
class Cachorro extends Animal {
public function fazerSom() {
echo "O cachorro late";
}
}
class Pato extends Animal {
// O Pato não deveria ter o método fazerSom alterado assim
public function nadar() {
echo "O pato nada";
}
}
function fazerAnimaisFazeremSom(Animal $animal) {
$animal->fazerSom(); // Espera-se que o Animal faça um som
}
$dog = new Cachorro();
$fazendoSom = fazerAnimaisFazeremSom($dog); // Espera "O cachorro late"
$duck = new Pato();
$fazendoSom = fazerAnimaisFazeremSom($duck); // AQUI pode gerar erro, pois Pato não implementou fazerSom corretamente.
?>
No código acima, quando substituímos Animal
por Pato
, a função fazerAnimaisFazeremSom
não vai funcionar corretamente, pois Pato
não implementa o método fazerSom
. Isso viola o LSP, pois estamos quebrando a expectativa do sistema de que qualquer Animal
pode fazer um som.
Código com o Princípio de Liskov (respeitando LSP)
Agora, vamos corrigir o código de forma que respeite o Princípio de Liskov, garantindo que a substituição seja segura:
php
CopiarEditar
<?php
class Animal {
public function fazerSom() {
echo "O animal faz um som";
}
}
class Cachorro extends Animal {
public function fazerSom() {
echo "O cachorro late";
}
}
class Pato extends Animal {
public function fazerSom() {
echo "O pato grasna";
}
}
function fazerAnimaisFazeremSom(Animal $animal) {
$animal->fazerSom(); // Agora, todos os animais podem fazer um som
}
$dog = new Cachorro();
echo "Cachorro: ";
fazerAnimaisFazeremSom($dog); // Espera "O cachorro late"
echo "\n";
$duck = new Pato();
echo "Pato: ";
fazerAnimaisFazeremSom($duck); // Espera "O pato grasna"
?>
Explicação
Agora, tanto o Cachorro quanto o Pato implementam o método fazerSom()
, que é o que o sistema espera de qualquer Animal
. Isso significa que qualquer objeto que seja uma instância de Animal
ou suas subclasses pode ser utilizado no lugar da classe Animal
sem que o sistema tenha problemas.
- A classe
Cachorro
e a classePato
são "substituíveis" sem quebrar o código, porque ambas mantêm a expectativa de que o métodofazerSom
existe. - Com isso, o código agora funciona corretamente e é mais flexível, pois podemos adicionar novos animais (como
Gato
,Vaca
, etc.) sem causar problemas, desde que implementemfazerSom
.
Conclusão
O Princípio de Substituição de Liskov nos ensina que, quando criamos subclasses, devemos garantir que elas possam ser usadas no lugar de suas classes base sem causar falhas ou resultados inesperados. Isso ajuda a manter o código robusto, fácil de entender e de manter.
No nosso exemplo em PHP, ao garantir que todas as subclasses implementem o método esperado (fazerSom
), conseguimos substituir um tipo por outro sem problemas, seguindo o LSP.
Gostou? Me segue nas redes sociais
Linkedin: https://www.linkedin.com/in/giuliano-criscuoli/
Github: https://github.com/GiulianoCriscuoli
Instagram: @giucriscuoli e @southlaser