O documento discute o Princípio da Substituição de Liskov (LSP), um dos cinco princípios do SOLID para programação orientada a objetos. O LSP estabelece que classes derivadas devem ser substituíveis por suas classes base sem alterar o comportamento do programa. O documento ilustra uma violação do LSP ao herdar uma classe Quadrado de uma classe Retângulo, alterando inadvertidamente seu comportamento.
1. LSP – The Liskov Substitution Principle
Elias Rodrigues de Oliveira
Gabriela Borges Diniz Teixeira
Prof. Edgard Davidson
Centro Universitário UNA
Engenharia de Software Centrada em Métodos Ágeis – Programação Orientação a Objetos
11/06/2011
RESUMO
Liskov Substitution Principle (LSP) é um dos cinco princípios do SOLID (acróstico onde cada letra significa a
sigla de um princípio: SRP, OCP, LSP, ISP e DIP). O Princípio da Substituição de Liskov tem como resumo que
as classes derivadas devem ser substituíveis por sua classe base, assim como os outros princípios do SOLID,
foram formulados como linguagens estáticas e, por essa razão precisam ser “adaptados” para que sejam
aplicados em linguagens dinâmicas. Em suas formas originais, esses princípios em geral recorrem a técnicas
como herança para contornar as “amarras” dos sistema estático de tipos.
Palavras-chave: LSP; Liskov Substitution Principle; Princípio da Substituição de Liskov.
1 INTRODUÇÃO
Na programação orientada a objeto, o princípio da substituição de Liskov é uma
definição particular para o conceito de subtipo. Foi introduzido em 1993 por Barbara Liskov e
Jeannette Wing através de um artigo de nome Family Values: A Behavioral Notion of
Subtyping.
O princípio LSP foi definido de forma resumida como:
Se q(x) é uma propriedade demonstrável dos objetos x de tipo T. Então q(y) deve ser
verdadeiro para objetos y de tipo S onde S é um subtipo de T.
Nas entrelinhas, se você pode invocar um método q() de uma classe T (base), deve
poder também invocar o método q() de uma classe T’ (derivada) que é derivada com herança
de T (base).
De forma bem simples, o princípio de Liskov sugere que, sempre que uma classe
cliente esperar uma instância de uma classe base X, uma instância de uma subclasse Y de X
pode ser substituída e ser usada no seu lugar.
Em outras palavras, uma classe base pode ser substituída pela sua classe derivada. O
objetivo é ter certeza de que novas classes derivadas estão estendendo das classes base, mas
sem alterar seu comportamento.
2 ENTENDENDO O LSP NA PRÁTICA: VIOLANDO O LSP
Para ilustrar o princípio LSP, utilizaremos um exemplo clássico. Suponhamos um
projeto que implementa duas classes: Retângulo e Quadrado.
A classe Quadrado é um Retângulo que tem uma característica especial: a largura e a
altura são iguais.
2. 2
Definimos duas classes para representar ambas as contas.
A notação UML ao lado ilustra o relacionamento de herança
existente entre duas classes onde temos que Quadrado é a classe
derivada e Retângulo é a classe Base.
No entanto, esse tipo de pensamento pode levar a alguns
problemas sutis, mas significativos.
Como a classe Quadrado herda da classe Retângulo, ela também
herdará os métodos da classe Retângulo, o que para um quadrado não
faz muito sentido visto que a largura e a altura não são iguais. É por isso
que se sobscreve esses métodos na classe Quadrado e define a largura
igual a altura.
Se as definições do projeto estiverem de acordo com o princípio LSP, a utilização da
classe Quadrado() deverá poder ser usada sem problemas no lugar da classe base Retângulo.
Se o princípio LSP estivesse sendo corretamente aplicado o fato de usar a instância de
Quadrado não implicaria em mudança de comportamento.
Ao criar um novo Retângulo definindo altura 5 e largura 10, para obter a área, o
resultado deveria ser 50, mas obtemos 100.
Este problema acontece pois, ao definirmos a largura para 10, acabamos definindo a
altura 10, deixando a área com valor 100 e não 50, como era esperado.
Neste caso um Quadrado não é um Retângulo, e ao aplicarmos o princípio “É-Um”
(Is-A) da herança de forma automática, vimos que ele não funciona para todos os casos.
A instância da classe Quadrado quando usada, quebra o código produzindo um
resultado errado e isso viola o princípio de Liskov, onde uma classe filha (Quadrado) deve
poder substituir uma classe base (Retângulo).
Para obter o resultado correto, basta alterar o código do método estático.
Fazendo isso o método fica correto, mas mostra que não se pode usar a instância
Quadrado como Retângulo.
5 CONCLUSÃO
Este exemplo mostra uma violação clara do princípio LSP onde a inclusão da classe
Quadrado herdando de Retângulo, mudou o comportamento da classe base, violando assim o
princípio Open-Closed.
O princípio LSP é uma extensão do Princípio Open-Closed, isso significa que deve-se
ter certeza de que as novas classes derivadas estão estendendo as classes base, sem alterar seu
comportamento.
6 REFERÊNCIAS
http://davidhayden.com/blog/dave/archive/2005/06/10/1226.aspx
http://www.objectmentor.com/resources/articles/lsp.pdf
http://www.objectmentor.com/omSolutions/oops_what.html
http://javaboutique.internet.com/tutorials/JavaOO/
http://www.engr.mun.ca/~theo/Courses/ssd/pub/sd-principles-3.pdf