CodeGym /Cursos /JAVA 25 SELF /Abstração em POO: por que e como aplicar

Abstração em POO: por que e como aplicar

JAVA 25 SELF
Nível 19, Lição 0
Disponível

1. Conceito de abstração

Em poucas palavras: abstração é a arte de enxergar coisas complexas de forma simples.

Na programação, abstração é o processo de identificar características e comportamentos comuns de um grupo de objetos, enquanto detalhes específicos (por exemplo, como exatamente algo funciona “sob o capô”) são ignorados. Imagine que você desenha um mapa da cidade: nele estão marcadas ruas, prédios, rios – mas não há detalhes como a cor das cortinas de cada janela. O mapa é uma abstração da cidade.

Em POO, abstração é criar classes e interfaces que refletem apenas as propriedades e ações importantes para a tarefa, ocultando detalhes desnecessários.

Exemplos do dia a dia

  • Transporte – é uma abstração. Não importa se é um ônibus, uma bicicleta ou uma nave espacial – o importante é que o transporte tem algo em comum: pode se deslocar, tem passageiros e um motorista.
  • Animal – também é uma abstração. Todos os animais podem respirar, comer, mover-se – mas como exatamente fazem isso depende da espécie.
  • Pagamento – é uma abstração em software bancário. Nem sempre importa se o pagamento é por cartão, via PayPal ou em bitcoins – o importante é que ele possa ser processado e retornar um resultado.

Por que a abstração é importante?

  • Pensar menos em detalhes que não são importantes para resolver a tarefa atual.
  • Projetar sistemas que sejam mais fáceis de estender e manter.
  • Trabalhar com objetos por meio de uma interface comum, sem se preocupar com a implementação concreta.

2. Abstração em Java

Em Java, a abstração é implementada por dois instrumentos principais:

  1. Classes abstratas (abstract class)
  2. Interfaces (interface)

Nesta aula, vamos focar em classes abstratas. (Chegaremos às interfaces muito em breve!)

Uma classe abstrata é uma classe que não se destina à criação de objetos diretamente. Ela define uma base comum (um molde) para outras classes. Em uma classe abstrata é possível definir tanto métodos implementados (com corpo) quanto métodos abstratos (sem corpo) – aqueles que precisam obrigatoriamente ser implementados nas subclasses.

Um método abstrato é um método sem implementação, ou seja, sem corpo. Ele indica: “Todos os descendentes desta classe devem implementar este método à sua maneira”.

Exemplo: abstração “Figura”

public abstract class Shape {
    public abstract void draw(); // Método abstrato — sem corpo!
}

Aqui estamos dizendo: “Todas as figuras sabem se desenhar, mas eu não sei como exatamente – que cada descendente decida por si”.

Por que nem sempre é preciso conhecer os detalhes da implementação?

Quando você usa uma abstração, trabalha com o objeto por meio de sua “face” – o conjunto de métodos que ele deve suportar. Como exatamente esse método funciona não importa.

Por exemplo, você chama payment.process() em um objeto para processar um pagamento. Não importa como está implementado – contanto que funcione. Isso permite:

  • Substituir uma implementação por outra sem reescrever o código que a utiliza.
  • Simplificar os testes (é possível substituir implementações por “stubs”).
  • Tornar o código mais flexível e resiliente a mudanças.

3. Vantagens da abstração

Simplificação do projeto e da manutenção do código
A abstração permite não pensar no que é supérfluo. Você não precisa saber como o motor de um carro é construído para dirigi-lo – bastam o volante, os pedais e a instrução “seguir em frente”. No código é igual: se você trabalha com uma classe abstrata ou interface, vê apenas o que precisa.

Facilidade de expansão do sistema
Quando seu sistema é construído com abstrações, é fácil adicionar novos tipos de objetos. Por exemplo, se você tem uma classe abstrata Shape, pode adicionar um novo tipo de figura – Triangle – sem alterar o código antigo.

Redução do acoplamento entre componentes
Se partes diferentes do programa se comunicam apenas por meio de abstrações, elas podem ser alteradas independentemente umas das outras. É como tomada e plugue: se o padrão coincide, você pode conectar qualquer aparelho à tomada.

4. Exemplos práticos

Vamos ver como a abstração funciona na prática. Usaremos exemplos que você pode incorporar no seu aplicativo de estudos para experimentar com as próprias mãos.

Exemplo 1: classe “Shape” (Figura)

public abstract class Shape {
    public abstract void draw();
}

Agora vamos criar algumas figuras concretas:

public class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("Desenhando um círculo");
    }
}

public class Rectangle extends Shape {
    @Override
    public void draw() {
        System.out.println("Desenhando um retângulo");
    }
}

Usando a abstração:

Shape s1 = new Circle();
Shape s2 = new Rectangle();

s1.draw(); // Desenhando um círculo
s2.draw(); // Desenhando um retângulo

Aqui trabalhamos com variáveis do tipo Shape – e não importa qual figura está por baixo. Essa é a força da abstração!

Exemplo 2: classe “Payment”

public abstract class Payment {
    public abstract void process();
}

Implementações concretas:

public class CreditCardPayment extends Payment {
    @Override
    public void process() {
        System.out.println("Processando pagamento com cartão de crédito");
    }
}

public class PaypalPayment extends Payment {
    @Override
    public void process() {
        System.out.println("Processando pagamento via PayPal");
    }
}

Uso:

Payment[] payments = {
    new CreditCardPayment(),
    new PaypalPayment()
};

for (Payment p : payments) {
    p.process();
}

Como resultado, cada pagamento é processado à sua maneira, mas o código que os chama não precisa se preocupar com isso.

5. Abstração e detalhes de implementação: como não se confundir

Abstração é o “o quê”, não o “como”

Ao projetar uma abstração, você responde à pergunta: “O que o objeto deve ser capaz de fazer?”
Os detalhes de implementação respondem: “Como ele faz isso?”.

Por exemplo:

  • Abstração: “Qualquer figura deve ser capaz de se desenhar (draw()).”
  • Detalhes de implementação: “Um círculo é desenhado com uma circunferência, um retângulo – com quatro linhas.”

Uma analogia do dia a dia

Lembre-se do controle remoto da TV. Você não se preocupa com como ele transmite o sinal – o importante é que exista um botão “ligar”, “mudar de canal” e “aumentar o volume”. Isso é a abstração – o conjunto de botões que você pode pressionar. Já os engenheiros que projetam o controle precisam pensar nos detalhes da implementação.

6. Como identificar abstrações no programa

Etapa 1. Encontre os pontos em comum

Observe os objetos do seu domínio. O que eles têm em comum? Por exemplo, todos os veículos podem andar, todos os animais podem comer, todos os pagamentos podem ser processados.

Etapa 2. Defina a classe abstrata

Crie uma classe abstrata que contenha apenas o que é comum a todos os objetos.

public abstract class Transport {
    public abstract void move();
}

Etapa 3. Implemente os detalhes nas subclasses

public class Car extends Transport {
    @Override
    public void move() {
        System.out.println("O carro anda pela estrada");
    }
}

public class Bicycle extends Transport {
    @Override
    public void move() {
        System.out.println("A bicicleta pedala");
    }
}

Etapa 4. Use a abstração no código

Transport[] transports = {
    new Car(),
    new Bicycle()
};

for (Transport t : transports) {
    t.move();
}

Seu código trabalha com abstrações – e não depende dos detalhes de implementação.

7. Abstração versus detalhamento: equilíbrio

Erro típico de iniciante – tentar fazer uma abstração detalhada demais ou, ao contrário, genérica demais.

  • Se a abstração é genérica demais (por exemplo, uma classe “Object” com um método “doSomething”), ela não traz nenhum benefício.
  • Se a abstração é detalhada demais (por exemplo, “Círculo com contorno vermelho e raio 5”), ela perde o sentido – é mais simples escrever logo a classe concreta.

Regra de ouro: a abstração deve refletir apenas o que é realmente comum e importante para a sua tarefa.

8. Erros comuns ao trabalhar com abstração

Erro nº 1: tentar criar um objeto de uma classe abstrata.
Classes abstratas não se destinam à criação de objetos diretamente. Se você tentar escrever Shape s = new Shape();, o compilador emitirá um erro: Cannot instantiate the type Shape. É como tentar comprar apenas “transporte” na loja. Não dá: é preciso escolher uma bicicleta, um carro ou um ônibus específico.

Erro nº 2: esquecer de implementar um método abstrato na subclasse.
Se uma classe herda de uma classe abstrata, mas não implementa todos os seus métodos abstratos, ela também se torna abstrata – e não pode ser instanciada. Verifique se você implementou todos os métodos obrigatórios.

Erro nº 3: misturar abstração e detalhes de implementação.
Se você começa a adicionar à classe abstrata detalhes necessários apenas para uma subclasse, isso é um sinal de uma abstração ruim. Por exemplo, se na classe abstrata Payment aparece o campo cardNumber, mas nem todos os pagamentos são feitos por cartão.

Erro nº 4: exagerar no uso de abstrações.
Não faça abstração por fazer. Se no seu sistema existe apenas um tipo de objeto e ele nunca será estendido, a abstração só vai complicar o código.

1
Tarefa
JAVA 25 SELF, nível 19, lição 0
Bloqueado
Projetando o reino animal 🦁
Projetando o reino animal 🦁
1
Tarefa
JAVA 25 SELF, nível 19, lição 0
Bloqueado
Adicionando um cachorro ao zoológico 🐶
Adicionando um cachorro ao zoológico 🐶
1
Tarefa
JAVA 25 SELF, nível 19, lição 0
Bloqueado
Dando vida ao transporte na cidade 🚗🚲
Dando vida ao transporte na cidade 🚗🚲
1
Tarefa
JAVA 25 SELF, nível 19, lição 0
Bloqueado
Desenvolvendo um módulo de pagamento online 💳
Desenvolvendo um módulo de pagamento online 💳
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION