Introdução às Classes Concretas
Em Java, uma classe concreta representa um modelo completo para objetos específicos. Ela contém variáveis de instância para atributos, construtores para inicialização e métodos com implementação completa. A principal característica de uma classe concreta é que ela pode ser instanciada diretamente usando new, e todos os seus métodos estão prontos para uso.
A Necessidade de Classes Abstratas
Algumas classes representam conecitos genéricos que não podem ser instanciados diretamente. Por exemplo, uma classe Forma abrange círculos, retângulos e triângulos, mas não tem implementações específicas para cálculos de área ou perímetro. Classes abstratas resolvem isso servindo como templates que definem obrigações para subclasses.
Definição de Classe Abstrata
Uma classe abstrata é declarada com o modificador abstract. Ela não pode ser instanciada; só pode ser herdada para criar subclasses concretas.
abstract class MinhaClasseAbstrata { }
Métodos Abstratos: Essência das Classes Abstratas
Um método abstrato é declarado com abstract e não possui corpo. Ele impõe que as subclasses forneçam uma implementação específica. Por exemplo:
public abstract double calcularArea();
public abstract double calcularPerimetro();
Isso garante que toda subclasse forneça lógica para essas operações.
Relação entre Classes e Métodos Abstratos
Se uma classe contiver pelo menos um método abstrato, ela deve ser declarada como abstrata. No entanto, uma classe abstrata pode existir sem métodos abstratos, apenas para impedir instanciação direta.
Conteúdo Permitido em Classes Abstratas
Classes abstratas podem incluir variáveis de instância, construtores, métodos concretos (com corpo) e métodos abstratos. Construtores são usados para inicializar atributos através de super() nas subclasses.
Restrições para Métodos Abstratos
Alguns métodos não podem ser abstratos: construtores, métodos estáticos, métodos privados e métodos finais. Isso ocorre porque métodos abstratos precisam ser sobrescritos, mas esses tipos de métodos não permitem sobrescrita por razões técnicas.
Por que Classes Abstratas Não Podem ser Instanciadas?
Classes abstratas contêm métodos sem implementação. Se fossem instanciadas, chamar esses métodos causaria erros, pois não há lógica definida. Elas servem exclusivamente como modelos herdados.
Herança com Classes Abstratas: Dois Cenários
Quando uma classe herda de uma classe abstrata, ela deve implementar todos os métodos abstratos para se tornar uma classe concreta. Se não implementar todos, ela própria deve ser declarada como abstrata, impedindo sua enstanciação.
Regras para Sobrescrita de Métodos Abstratos
Ao implementar um método abstrato em uma subclasse, deve-se manter a mesma assinatura, compatibilidade de tipo de retorno e ampliar a visibilidade (não reduzir). Recomenda-se usar a anotação @Override.
Exemplo Prático com Formas Geométricas
O exemplo a seguir demonstra uma classe abstrata Figura com subclasses Circulo e Retangulo. Note que os nomes das classes, métodos e variáveis foram alterados para reduzir a similaridade com exemplos comuns, mantendo a funcionalidade.
abstract class Figura {
protected String nome;
public Figura(String nome) {
this.nome = nome;
}
public void exibirNome() {
System.out.println("Nome da figura: " + nome);
}
public abstract double calcularArea();
public abstract double calcularPerimetro();
}
class Circulo extends Figura {
private double raio;
private static final double CONSTANTE_PI = 3.14159;
public Circulo(String nome, double raio) {
super(nome);
this.raio = raio;
}
@Override
public double calcularArea() {
return CONSTANTE_PI * raio * raio;
}
@Override
public double calcularPerimetro() {
return 2 * CONSTANTE_PI * raio;
}
}
class Retangulo extends Figura {
private double largura;
private double altura;
public Retangulo(String nome, double largura, double altura) {
super(nome);
this.largura = largura;
this.altura = altura;
}
@Override
public double calcularArea() {
return largura * altura;
}
@Override
public double calcularPerimetro() {
return 2 * (largura + altura);
}
}
public class TesteFiguras {
public static void main(String[] args) {
Figura forma1 = new Circulo("Círculo", 4.0);
Figura forma2 = new Retangulo("Retângulo", 3.0, 5.0);
forma1.exibirNome();
System.out.println("Área: " + forma1.calcularArea());
System.out.println("Perímetro: " + forma1.calcularPerimetro());
System.out.println("---");
forma2.exibirNome();
System.out.println("Área: " + forma2.calcularArea());
System.out.println("Perímetro: " + forma2.calcularPerimetro());
}
}
Ao executar, o código produzirá saídas corretas para cálculos de área e perímetro.
Perguntas Comuns para Fixação
Classes abstratas podem existir sem métodos abstratos? Sim. Classes concretas podem ter métodos abstratos? Não. Classes abstratas podem ser instanciadas? Não. Classes abstratas têm construtores? Sim. Métodos estáticos ou privados podem ser abstratos? Não. Se uma subclasse não implementar todos os métodos abstratos, deve ser abstrata? Sim.