Atualizado: 09/08/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Classes Abstratas em Java

No Java, além das classes comuns, existem as classes abstratas. Uma classe abstrata pode conter atributos e métodos como qualquer outra, mas não pode ser instanciada diretamente. Seu papel é servir como modelo base para outras classes, oferecendo uma estrutura e, muitas vezes, parte da implementação que será compartilhada pelas subclasses.

Definição

O modificador abstract é usado na declaração da classe:

public abstract class Human {

    private String name;

    public String getName() {
        return name;
    }
}

A principal diferença em relação a uma classe comum é que não é possível criar um objeto dela diretamente:

Human h = new Human(); // Erro: não é possível instanciar uma classe abstrata

Métodos abstratos

Além de métodos comuns (com corpo), uma classe abstrata pode declarar métodos abstratos, que não têm implementação e terminam com ponto e vírgula:

public abstract void display();

⚠️ Regras importantes:

  • Qualquer classe concreta que herde de uma classe abstrata deve implementar todos os métodos abstratos herdados.
  • Se uma classe declarar pelo menos um método abstrato, ela própria precisa ser marcada como abstract.

Exemplo prático: Sistema bancário

Imagine um sistema para gerenciar operações bancárias. Há três classes principais: Person (pessoa), Employee (funcionário do banco) e Client (cliente do banco). As duas últimas compartilham atributos e comportamentos comuns de Person, mas não existe uma instância genérica de pessoa no sistema. Nesse caso, faz sentido tornar Person abstrata.

public class Program {
    public static void main(String[] args) {

        Employee sam = new Employee("Sam", "Lehman Brothers");
        sam.display();

        Client bob = new Client("Bob", "Lehman Brothers");
        bob.display();
    }
}

abstract class Person {

    private String name;

    public String getName() {
        return name;
    }

    public Person(String name) {
        this.name = name;
    }

    public abstract void display();
}

class Employee extends Person {

    private String bank;

    public Employee(String name, String company) {
        super(name);
        this.bank = company;
    }

    @Override
    public void display() {
        System.out.printf("Employee Name: %s \t Bank: %s%n", getName(), bank);
    }
}

class Client extends Person {

    private String bank;

    public Client(String name, String company) {
        super(name);
        this.bank = company;
    }

    @Override
    public void display() {
        System.out.printf("Client Name: %s \t Bank: %s%n", getName(), bank);
    }
}

Resumo do exemplo:

  • Person define atributos e comportamentos comuns, mas não pode ser instanciada.
  • Employee e Client herdam de Person e implementam o método abstrato display() de forma específica.

Exemplo clássico: Geometria

No mundo real, “figura” é um conceito genérico — não existe uma figura sem forma definida. Mas figuras concretas como círculos, retângulos e quadrados compartilham características comuns, que podem ser representadas em uma classe abstrata Figure.

// Classe abstrata para figuras
abstract class Figure {

    float x; // coordenada X
    float y; // coordenada Y

    Figure(float x, float y) {
        this.x = x;
        this.y = y;
    }

    // Método abstrato para perímetro
    public abstract float getPerimeter();

    // Método abstrato para área
    public abstract float getArea();
}

// Subclasse concreta: Retângulo
class Rectangle extends Figure {

    private float width;
    private float height;

    Rectangle(float x, float y, float width, float height) {
        super(x, y);
        this.width = width;
        this.height = height;
    }

    @Override
    public float getPerimeter() {
        return (width * 2) + (height * 2);
    }

    @Override
    public float getArea() {
        return width * height;
    }
}

Resumo do exemplo:

  • Figure define os atributos de posição e os métodos abstratos getPerimeter() e getArea().
  • Rectangle fornece implementações concretas para calcular perímetro e área.
  • Outras figuras, como Circle ou Square, podem herdar de Figure e implementar os mesmos métodos, mantendo consistência na API.

📝 Exercícios

Tarefa 1 — Identificar uso incorreto de classe abstrata

Descrição: Analise o código abaixo e indique o motivo do erro de compilação.

abstract class Shape {
    public abstract double getArea();
}

public class Program {
    public static void main(String[] args) {
        Shape s = new Shape();
    }
}
Resposta

O erro ocorre porque classes abstratas não podem ser instanciadas diretamente. Para usar Shape, é necessário criar uma subclasse concreta que implemente o método getArea().

Explicação: O modificador abstract impede a criação de objetos dessa classe. Ele indica que a implementação está incompleta e precisa ser finalizada por subclasses concretas.


Tarefa 2 — Implementar métodos abstratos

Descrição: Implemente a classe Circle como subclasse de Figure para calcular área e perímetro.

abstract class Figure {
    public abstract double getPerimeter();
    public abstract double getArea();
}
Resposta

Solução:

class Circle extends Figure {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double getPerimeter() {
        return 2 * Math.PI * radius;
    }

    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

Explicação: A classe Circle é concreta, portanto precisa implementar todos os métodos abstratos de Figure. Cada método retorna o cálculo correspondente usando o valor do raio.


Tarefa 3 — Polimorfismo com classes abstratas

Descrição: Dado o código a seguir, identifique a saída no console.

abstract class Person {
    String name;
    public Person(String name) {
        this.name = name;
    }
    public abstract void display();
}

class Employee extends Person {
    String company;
    public Employee(String name, String company) {
        super(name);
        this.company = company;
    }
    @Override
    public void display() {
        System.out.println("Employee " + name + " works at " + company);
    }
}

public class Program {
    public static void main(String[] args) {
        Person p = new Employee("Sam", "Oracle");
        p.display();
    }
}
Resposta

Saída esperada:

Employee Sam works at Oracle

Explicação: Embora a variável p seja do tipo Person, a instância real é de Employee. O método display() é sobrescrito na subclasse e chamado dinamicamente em tempo de execução (polimorfismo).

Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com