Classes Abstratas
Em Java, classes e métodos marcados com a palavra-chave abstract definem comportamentos que as subclasses devem implementar. Um método abstrato contém apenas a assinatura, sem corpo.
Regras para classes abstratas:
- Uma classe pode ser abstrata mesmo sem métodos abstratos, mas se tiver métodos abstratos, deve ser declarada como abstrata.
- Elas podem conter campos, métodos concretos e construtores, como classes comuns.
- Não é possível instanciar uma classe abstrata diretamente; ela serve como modelo para herança.
- Subclasses que herdam de uma classe abstrata devem implementar todos os seus métodos abstratos, ou serem também abstratas.
Classes abstratas são ideais quando se deseja padronizar um comportamento que varia entre subclasses, promovendo polimorfismo. O padrão Template Method aproveita isso ao definir métodos abstratos para etapas específicas, enquanto mantém a estrutura comum em métodos concretos com final.
Interfaces
Interfaces, definidas com a palavra-chave interface, estabelecem contratos que classes implementadoras devem cumprir. Uma classe pode implementar múltiplas interfaces, permitindo a herança múltipla de funcionalidades.
Vantagens das interfaces:
- Resolvem limitações de herança única em Java, permitindo que classes ampliem seu comportamento através de múltiplos "contratos".
- Promovem a programação orientada a interfaces, facilitando a troca flexível de implementações em tempo de execução.
A partir do JDK 8, interfaces podem incluir métodos default, métodos estáticos e, do JDK 9 em diante, métodos privados, aumentando sua capacidade de reuso e manutenção.
Regras de herança em interfaces:
- Uma interface pode herdar de várias enterfaces.
- Conflitos em assinaturas de métodos podem impedir a herança ou implementação múltipla.
- Quando uma classe herda de uma classe pai e implementa interfaces, métodos da classe pai têm prioridade sobre métodos
defaultdas interfaces.
Estudo de Caso: Gerenciamento de Estudantes
Requisito: Desenvolver um módulo para gerenciar informações de estudantes, incluindo nome, gênero e pontuação. Funcionalidades necessárias: exibir dados de todos os estudantes e calcular a média das pontuações.
Duas implementações são propostas:
- Implementação básica que lista informações e calcula a média simples.
- Implementação avançada que inclui contagem por gênero e calcula a média aparada (excluindo a maior e menor pontuação).
O sistema deve permitir alternância flexível entre essas implementações usando polimorfismo.
Exemplos de Código
package com.example.gestao;
// Classe Aluno representa um estudante com nome, gênero e pontuação.
public class Aluno {
private String nome;
private char genero;
private double pontuacao;
public Aluno() {
}
public Aluno(String nome, char genero, double pontuacao) {
this.nome = nome;
this.genero = genero;
this.pontuacao = pontuacao;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public char getGenero() {
return genero;
}
public void setGenero(char genero) {
this.genero = genero;
}
public double getPontuacao() {
return pontuacao;
}
public void setPontuacao(double pontuacao) {
this.pontuacao = pontuacao;
}
}
package com.example.gestao;
import java.util.List;
// Interface Impressao define métodos para exibição de informações de estudantes.
public interface Impressao {
void mostrarDados(List<aluno> alunos);
void calcularMedia(List<aluno> alunos);
}
</aluno></aluno>
package com.example.gestao;
import java.util.List;
// Primeira implementação: exibe informações básicas e calcula média simples.
public class ImplementacaoImpressao1 implements Impressao {
@Override
public void mostrarDados(List<aluno> alunos) {
for (Aluno aluno : alunos) {
System.out.println("Nome: " + aluno.getNome());
System.out.println("Gênero: " + aluno.getGenero());
System.out.println("Pontuação: " + aluno.getPontuacao());
}
}
@Override
public void calcularMedia(List<aluno> alunos) {
double total = 0.0;
for (Aluno aluno : alunos) {
total += aluno.getPontuacao();
}
System.out.println("Média simples: " + total / alunos.size());
}
}
</aluno></aluno>
package com.example.gestao;
import java.util.List;
// Segunda implementação: exibe dados com contagem de gênero e calcula média aparada.
public class ImplementacaoImpressao2 implements Impressao {
@Override
public void mostrarDados(List<aluno> alunos) {
int masculino = 0;
int feminino = 0;
for (Aluno aluno : alunos) {
System.out.println("Nome: " + aluno.getNome());
System.out.println("Gênero: " + aluno.getGenero());
System.out.println("Pontuação: " + aluno.getPontuacao());
if (aluno.getGenero() == 'M') {
masculino++;
} else {
feminino++;
}
}
System.out.println("Contagem - Masculino: " + masculino + ", Feminino: " + feminino);
}
@Override
public void calcularMedia(List<aluno> alunos) {
double soma = 0.0;
double maior = alunos.get(0).getPontuacao();
double menor = alunos.get(0).getPontuacao();
for (Aluno aluno : alunos) {
double valor = aluno.getPontuacao();
soma += valor;
if (valor > maior) {
maior = valor;
}
if (valor < menor) {
menor = valor;
}
}
double mediaAparada = (soma - maior - menor) / (alunos.size() - 2);
System.out.println("Média aparada: " + mediaAparada);
}
}
</aluno></aluno>
package com.example.gestao;
import java.util.ArrayList;
import java.util.List;
// Classe GerenciadorAlunos orquestra as operações usando a interface Impressao.
public class GerenciadorAlunos {
private List<aluno> listaAlunos = new ArrayList<>();
private Impressao impressao = new ImplementacaoImpressao2(); // Alterar para ImplementacaoImpressao1 conforme necessário
public GerenciadorAlunos() {
listaAlunos.add(new Aluno("Lucas", 'M', 92));
listaAlunos.add(new Aluno("Beatriz", 'F', 85));
listaAlunos.add(new Aluno("Rafael", 'M', 78));
listaAlunos.add(new Aluno("Fernanda", 'F', 95));
}
public void exibirTodosDados() {
impressao.mostrarDados(listaAlunos);
}
public void exibirMediaPontuacao() {
impressao.calcularMedia(listaAlunos);
}
}
</aluno>
package com.example.gestao;
// Classe de teste para demonstrar o uso do gerenciador.
public class Teste {
public static void main(String[] args) {
GerenciadorAlunos gerenciador = new GerenciadorAlunos();
gerenciador.exibirTodosDados();
gerenciador.exibirMediaPontuacao();
}
}