13.14. Herança e Polimorfismo em Java: Princípio de Substituição de Liskov

A programação orientada a objetos (POO) é um paradigma de programação que utiliza "objetos" para modelar dados e comportamentos. Java, sendo uma linguagem orientada a objetos, permite que os programadores aproveitem conceitos como herança e polimorfismo para criar programas mais flexíveis e reutilizáveis. Vamos aprofundar nosso entendimento sobre esses conceitos e explorar o Princípio de Substituição de Liskov (LSP), um dos princípios fundamentais da programação orientada a objetos.

Herança em Java

Herança é um mecanismo pelo qual uma nova classe, chamada subclasse, pode herdar campos e métodos de outra classe, chamada superclasse. Isso permite que subclasses reutilizem e estendam o comportamento das superclasses. Em Java, a herança é realizada com a palavra-chave extends.


class Veiculo {
    public void mover() {
        System.out.println("Veículo em movimento");
    }
}

class Carro extends Veiculo {
    @Override
    public void mover() {
        System.out.println("Carro em movimento");
    }
}

No exemplo acima, Carro é uma subclasse de Veiculo. A subclasse Carro herda o método mover() e fornece sua própria implementação usando a anotação @Override. Isso ilustra a extensão e a reutilização de funcionalidades.

Polimorfismo em Java

Polimorfismo é a capacidade de um objeto ser tratado como uma instância de sua própria classe ou de qualquer classe da qual ele herda. Em Java, isso é comumente realizado através da sobrescrita de métodos (method overriding) e da sobrecarga de métodos (method overloading).

Com a sobrescrita de métodos, uma subclasse pode fornecer uma implementação específica de um método que já existe em sua superclasse. Já a sobrecarga de métodos permite que vários métodos tenham o mesmo nome, mas com diferentes listas de parâmetros.

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

O Princípio de Substituição de Liskov, formulado por Barbara Liskov em 1987, é um conceito fundamental na programação orientada a objetos. O LSP afirma que se S é um subtipo de T, então objetos do tipo T em um programa podem ser substituídos por objetos do tipo S sem alterar as propriedades desejáveis desse programa. Em outras palavras, uma subclasse deve ser substituível por sua superclasse sem causar erros.

Para aderir ao LSP, uma subclasse deve:

  • Não alterar o comportamento esperado dos métodos da superclasse.
  • Não violar as invariáveis e contratos estabelecidos pela superclasse.
  • Garantir que os subtipos possam ser usados em substituição aos tipos base sem que haja necessidade de conhecer a diferença entre eles.

Violar o LSP pode levar a bugs e comportamentos inesperados em um programa. Por exemplo:


class Passaro {
    public void voar() {
        System.out.println("Pássaro voando");
    }
}

class Pinguim extends Passaro {
    @Override
    public void voar() {
        throw new UnsupportedOperationException("Pinguins não voam");
    }
}

No exemplo acima, Pinguim é uma subclasse de Passaro, mas sobrescreve o método voar() para lançar uma exceção, pois pinguins não voam. Isso viola o LSP, pois o comportamento da superclasse Passaro é alterado de uma maneira que pode causar erros se objetos de Pinguim forem usados em contextos que esperam que todos os pássaros possam voar.

Como Aplicar o LSP em Java

Para garantir que o LSP seja respeitado em Java, siga estas diretrizes:

  • Evite sobrescrever métodos de uma forma que mude o comportamento esperado.
  • Use a anotação @Override ao sobrescrever métodos para garantir que você está de fato modificando um método da superclasse.
  • Quando necessário, use composição em vez de herança para compartilhar comportamentos entre classes que não têm uma relação de substituibilidade.
  • Respeite os contratos estabelecidos pela superclasse, incluindo pré-condições, pós-condições e invariantes.

Adotar o LSP ajuda a manter a integridade do design orientado a objetos, promovendo a criação de sistemas mais robustos e manuteníveis.

Conclusão

Herança e polimorfismo são conceitos poderosos em Java que, quando usados corretamente, podem aumentar a reutilização de código e flexibilidade. O Princípio de Substituição de Liskov é essencial para usar esses conceitos de forma eficaz, garantindo que as subclasses possam ser usadas em lugar de suas superclasses sem causar efeitos colaterais indesejados. Ao projetar e implementar suas classes em Java, mantenha sempre o LSP em mente para criar um código mais confiável e fácil de manter.

Agora responda o exercício sobre o conteúdo:

Qual das seguintes alternativas melhor descreve o Princípio de Substituição de Liskov (LSP) conforme explicado no texto?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

Imagem do artigo Classes e métodos abstratos

Próxima página do Ebook Gratuito:

99Classes e métodos abstratos

4 minutos

Ganhe seu Certificado deste Curso Gratuitamente! ao baixar o aplicativo Cursa e ler o ebook por lá. Disponível na Google Play ou App Store!

Disponível no Google Play Disponível no App Store

+ de 6,5 milhões
de alunos

Certificado Gratuito e
Válido em todo o Brasil

48 mil exercícios
gratuitos

4,8/5 classificação
nas lojas de apps

Cursos gratuitos em
vídeo, áudio e texto