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

Página 98

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.

Now answer the exercise about the content:

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

You are right! Congratulations, now go to the next page

You missed! Try again.

Next page of the Free Ebook:

9914. Classes e métodos abstratos

Earn your Certificate for this Course for Free! by downloading the Cursa app and reading the ebook there. Available on Google Play or App Store!

Get it on Google Play Get it on App Store

+ 6.5 million
students

Free and Valid
Certificate with QR Code

48 thousand free
exercises

4.8/5 rating in
app stores

Free courses in
video, audio and text