sábado, 4 de outubro de 2008

Princípios da Substituição de Liskov

O princípio de substituição de Liskov, criado por Bárbara Liskov, determina que funções que utilizam referências a classes base devem estar aptas a utilizar objetos de classes derivadas sem nem ao menos conhecê-los.

A importância deste princípio é obvia quando são consideradas as conseqüências de violá-lo. Por exemplo, seja “F” uma função que recebe como parâmetro uma classe base “B”. Presumindo que ao passar um objeto “D”, de uma classe derivada de “B”, cause um comportamento errado em “F”. Logo, “D” viola o princípio de substituição de Liskov e o mesmo é considerado frágil quando utilizado por “F”. Para testar esta função, deverá ser criado um teste particular para “F” ao receber “D” como parâmetro. Este teste viola o princípio aberto/fechado porque “F” não é fechado a extensões de “B”.

Como exemplo de violação do princípio, considere a aplicação que utiliza um retângulo. A princípio essa aplicação funciona corretamente, porém o cliente decide que a aplicação deve também trabalhar com um quadrado. Um quadrado não é nada mais que um retângulo com lados iguais, logo a classe quadrado deve derivar de retângulo. Costuma-se interpretar esse tipo de relacionamento de herança entre duas classes como “é um” ou “é um tipo de”, neste caso, quadrado é um tipo de retângulo como mostra a ilustração 1.

Ilustração 1 – Quadrado herda de Retângulo

Este tipo de análise de relacionamento é visto algumas vezes como uma das técnicas fundamentais da análise da orientação a objetos. Porém este tipo de análise pode induzir a erros significantes que apenas serão notados na implementação.

Uma falha que pode ser apontada no exemplo é o fato de que um quadrado não necessita ter as propriedades Base e Altura, uma vez que todos os lados do quadrado são iguais. Estas propriedades herdadas não são apropriadas quando o objeto em questão é um quadrado, porém é possível contornar a situação sobrescrevendo os métodos “get” e “set” da Base e da Altura para que quando alguém atribuir um valor à base, o método atribui o mesmo valor à altura e vice-versa.

Agora considere uma função onde é passado como parâmetro um retângulo:

Função fx(Retângulo r)
{
    r.base = 5;
    r.altura = 4;
    se (r.Area() != 20)
        //Exibe Erro: Área incorreta;
}

A função utiliza os atributos base e altura de um suposto retângulo. A função funciona corretamente quando lhe é passado um retângulo mas dá errada se um quadrado for passado. A função “fx” é frágil se levarmos em consideração a hierarquia quadrado/retângulo. A função citada viola o principio de substituição de Liskov já que é possível existir uma função que receba um retângulo como parâmetro e não funcione corretamente se for passado um quadrado, por este motivo o quadrado não é substituível por um retângulo, ou seja, sua classe base.


Nenhum comentário: