Princípio da Substituição de Liskov (LSP)

Definição

O Princípio da Substituição de Liskov (Liskov Substitution Principle - LSP) estabelece que subclasses devem poder ser usadas no lugar de suas superclasses sem alterar o comportamento esperado do sistema.

Isso significa que uma classe derivada deve preservar o contrato da classe base: seus métodos devem manter as mesmas expectativas e efeitos. Se isso não acontece, a substituição causa comportamentos inesperados — violando o LSP.

Esse é o terceiro princípio do SOLID, um conjunto de boas práticas para design orientado a objetos.

Exemplo prático (Python)

A classe Retangulo permite configurar largura e altura de forma independente e calcula a área corretamente:

class Retangulo:
    def __init__(self, largura, altura):
        self.largura = largura
        self.altura = altura

    def definir_largura(self, largura):
        self.largura = largura

    def definir_altura(self, altura):
        self.altura = altura

    def calcular_area(self):
        return self.largura * self.altura

Em seguida, criamos uma subclasse Quadrado que tenta adaptar o comportamento de Retangulo, mas com a restrição de que os dois lados sempre devem ser iguais:

class Quadrado(Retangulo):
    def definir_largura(self, valor):
        self.largura = valor
        self.altura = valor

    def definir_altura(self, valor):
        self.altura = valor
        self.largura = valor

Veja o comportamento esperado com Retangulo:

r = Retangulo(5, 4)
print(r.calcular_area())  # Saída: 20

E o comportamento com Quadrado:

q = Quadrado(5, 4)  # Problema: um quadrado deveria ter lados iguais!
print(q.calcular_area())  # Saída: 16 — comportamento inesperado

Embora Quadrado herde de Retangulo, ele não respeita o contrato da superclasse. O método calcular_area() deixa de refletir as dimensões configuradas, violando o LSP. O construtor de Retangulo aceita lados diferentes, mas essa lógica não se aplica corretamente a um quadrado — o que compromete a substituição segura.

Implementação correta que respeita o LSP

Em vez de fazer Quadrado herdar de Retangulo, o mais adequado é criar uma interface comum para formas geométricas e fazer com que cada classe implemente sua própria lógica de área:

from abc import ABC, abstractmethod

# Interface comum
class Forma(ABC):
    @abstractmethod
    def calcular_area(self):
        pass

# Implementação para Retângulo
class Retangulo(Forma):
    def __init__(self, largura, altura):
        self.largura = largura
        self.altura = altura

    def calcular_area(self):
        return self.largura * self.altura

# Implementação para Quadrado
class Quadrado(Forma):
    def __init__(self, lado):
        self.lado = lado

    def calcular_area(self):
        return self.lado * self.lado

# Exemplos de uso
retangulo = Retangulo(3, 6)
quadrado = Quadrado(4)

print(f"Área do retângulo: {retangulo.calcular_area()}")
print(f"Área do quadrado: {quadrado.calcular_area()}")

Dessa forma, Quadrado e Retangulo não violam o LSP, pois nenhum deles depende da lógica interna do outro. Cada um cumpre seu contrato de forma independente, sem alterar o comportamento esperado do sistema.

Consequências de ignorar o LSP

  • Quebra funcionalidades ao substituir subclasses
  • Introduz bugs difíceis de rastrear
  • Viola o contrato de uso da superclasse
  • Enfraquece a robustez de sistemas orientados a objetos

Relacionados

Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com