CodeGym /Cursos /JAVA 25 SELF /Classes e métodos abstratos: sintaxe e exemplos

Classes e métodos abstratos: sintaxe e exemplos

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

1. Sintaxe de uma classe abstrata

Vamos entender o que é uma classe abstrata em Java e por que ela é necessária. Imagine que você tem um conjunto LEGO: você tem um conjunto de peças (por exemplo, “rodas”, “blocos”) e há peças especiais para modelos específicos. Uma classe abstrata é como uma instrução genérica de como lidar com as peças sem descrever a montagem de um modelo específico: os blocos se conectam por encaixes, as rodas são presas aos eixos, as peças podem ser empilhadas em camadas. A classe abstrata descreve exatamente essas regras gerais e etapas obrigatórias, mas não detalha a montagem de um modelo concreto. Os modelos concretos são as subclasses: elas seguem a instrução geral e acrescentam as etapas que faltam.

Em Java, uma classe abstrata é uma classe que não pode ser instanciada diretamente (não é possível fazer new AbstractClass()), mas que pode ser estendida para implementar seus métodos “inacabados”.

Classes abstratas são úteis quando:

  • Um grupo de objetos tem comportamento ou estado em comum, mas parte da lógica é diferente.
  • Você quer implementar parte da funcionalidade “por padrão” e deixar outra parte para os filhos.
  • Você quer impedir a criação direta de objetos dessa classe (por exemplo, “Animal” por si só não existe, mas “Gato”, sim).

Como declarar uma classe abstrata

É simples: antes da palavra class, escreva a palavra-chave abstract.

public abstract class Animal {
    // Campos (por exemplo, o nome do animal)
    protected String name;

    // Construtor
    public Animal(String name) {
        this.name = name;
    }

    // Método abstrato — apenas declaração, sem implementação!
    public abstract void makeSound();

    // Método comum (com implementação)
    public void sleep() {
        System.out.println(name + " dorme: Zzz...");
    }
}

Particularidades:

  • Uma classe abstrata pode conter tanto métodos implementados quanto abstratos.
  • Uma classe abstrata pode conter campos, construtores e até métodos static.
  • Não é possível criar um objeto de uma classe abstrata diretamente:
  • Animal a = new Animal("Alguém"); // Erro!

Como declarar um método abstrato

Um método abstrato é um método sem corpo, ou seja, sem chaves e sem código dentro. Ele é declarado com a palavra-chave abstract e deve terminar com ponto e vírgula ;.

public abstract void makeSound();
  • Métodos abstratos só podem ser declarados dentro de uma classe abstrata.
  • Uma classe que herda de uma classe abstrata é obrigada a implementar todos os métodos abstratos; caso contrário, ela também deve ser abstract.

2. Herança de classes abstratas: como funciona

Vamos ver um exemplo concreto. Suponha que temos uma classe abstrata Animal com um método abstrato makeSound(). Agora vamos criar a classe filha Dog, que implementa esse método:

public class Dog extends Animal {
    public Dog(String name) {
        super(name); // Chamada do construtor da classe base
    }

    @Override
    public void makeSound() {
        System.out.println(name + " late: Au-au!");
    }
}

E mais uma classe filha:

public class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println(name + " mia: Miau!");
    }
}

Agora podemos usar essas classes no programa:

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog("Sharik");
        Animal cat = new Cat("Murka");

        dog.makeSound(); // Sharik late: Au-au!
        cat.makeSound(); // Murka mia: Miau!

        dog.sleep(); // Sharik dorme: Zzz...
        cat.sleep(); // Murka dorme: Zzz...
    }
}

Atenção:
Podemos declarar variáveis do tipo Animal, mas só podemos instanciar objetos de subclasses concretas (não abstratas).

Esquema: como fica


.         Animal (abstract)
            /         \
         Dog         Cat
 (implementa makeSound) (implementa makeSound)

3. Quando usar classe abstrata e quando usar interface?

Essa é uma das perguntas mais comuns em entrevistas — e com razão! Vamos entender:

  • Classe abstrata — quando os objetos têm estado (por exemplo, campos) em comum, lógica em comum (métodos com implementação) e você quer fornecer um “esqueleto” de comportamento com possibilidade de complementação.
  • Interface — quando você quer definir apenas um conjunto de métodos (contrato), sem implementação e sem estado. Desde o Java 8, interfaces possuem métodos default/static, mas ainda assim interface trata do “o que o objeto deve fazer”, não do “como ele faz”.

Exemplo do cotidiano:
“Ave” — classe abstrata: todas as aves têm bico, asas e podem voar (mas de formas diferentes).
“Voador” — interface: não só as aves voam, mas também aviões e super-heróis! Todos voam de maneiras diferentes, mas o importante é: eles conseguem voar.

4. Exemplos práticos

Exemplo 1: classe abstrata com implementação parcial

Suponha que você está fazendo um jogo com diferentes tipos de transporte. Todos podem se mover, mas fazem isso de formas diferentes. Porém, todos têm velocidade, nome e uma forma padrão de parar.

public abstract class Transport {
    protected String name;
    protected int speed;

    public Transport(String name, int speed) {
        this.name = name;
        this.speed = speed;
    }

    // Método abstrato — implementação nas subclasses
    public abstract void move();

    // Método implementado
    public void stop() {
        System.out.println(name + " parou.");
    }
}

public class Car extends Transport {
    public Car(String name, int speed) {
        super(name, speed);
    }

    @Override
    public void move() {
        System.out.println(name + " anda pela estrada a " + speed + " km/h.");
    }
}

public class Bicycle extends Transport {
    public Bicycle(String name, int speed) {
        super(name, speed);
    }

    @Override
    public void move() {
        System.out.println(name + " pedala a " + speed + " km/h.");
    }
}

Uso:

Transport car = new Car("Toyota", 120);
Transport bike = new Bicycle("Stels", 25);

car.move(); // Toyota anda pela estrada a 120 km/h.
bike.move(); // Stels pedala a 25 km/h.

car.stop(); // Toyota parou.
bike.stop(); // Stels parou.

Exemplo 2: método abstrato com parâmetro

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

public class Circle extends Shape {
    private double radius;
    public Circle(double radius) {
        this.radius = radius;
    }
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

public class Rectangle extends Shape {
    private double width, height;
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    @Override
    public double area() {
        return width * height;
    }
}

Uso:

Shape c = new Circle(3);
Shape r = new Rectangle(4, 5);

System.out.println("Área do círculo: " + c.area());
System.out.println("Área do retângulo: " + r.area());

5. Particularidades e nuances de classes abstratas

  • Uma classe abstrata pode usar quaisquer modificadores de acesso: public, protected, private (por exemplo, para campos).
  • É possível declarar uma classe abstrata sem métodos abstratos. Isso pode ser útil se você apenas quiser impedir a criação de instâncias da classe base.
  • Se uma classe herda de uma classe abstrata, mas não implementa todos os métodos abstratos, ela também deve ser declarada como abstract.
  • Uma classe abstrata pode ter construtores. Eles são chamados ao criar um objeto da subclasse (via super(...)).
  • Métodos abstratos não podem ser private (caso contrário, não será possível implementá-los na subclasse).
  • Classes abstratas podem conter métodos e campos static.
  • Uma classe abstrata pode implementar interfaces, mas não é obrigada a implementar seus métodos — isso pode ser feito pelas subclasses.

Tabela: comparação entre classe abstrata e interface

Classe abstrata Interface
Palavra-chave
abstract class
interface
Pode conter campos Sim (quaisquer) Desde o Java 8 — apenas static/final
Métodos com implementação Sim Desde o Java 8 — default/static
Métodos abstratos Sim Sim
Herança múltipla Não Sim (é possível implementar várias interfaces)
Construtores Sim Não
Pode criar objeto Não Não

6. Erros comuns ao trabalhar com classes e métodos abstratos

Erro nº 1: tentativa de instanciar uma classe abstrata.
Se você escrever new Animal("Alguém"), o compilador lembrará imediatamente que classes abstratas não se destinam a isso. Lembre-se: abstração é um “esqueleto”, não um “organismo vivo”.

Erro nº 2: esqueceu de implementar todos os métodos abstratos na subclasse.
Se sua classe não implementar pelo menos um método abstrato da classe base, ela própria deve ser declarada como abstract; caso contrário, você terá um erro de compilação.

Erro nº 3: declarou um método abstrato fora de uma classe abstrata.
Em Java, não é permitido declarar um método abstrato em uma classe comum (não abstrata) — o compilador reclamará imediatamente.

Erro nº 4: tentar tornar um método abstrato private ou static.
Métodos abstratos não podem ser private (caso contrário, não podem ser sobrescritos) e não podem ser static (porque métodos estáticos não são sobrescritos). E também não podem ser final, porque final impede a sobrescrita.

Erro nº 5: esqueceu o modificador de acesso do método abstrato.
Se você não especificar explicitamente um modificador, o método terá visibilidade de pacote (package-private), o que às vezes não é o que você pretendia.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION