O polimorfismo é um dos pilares da Programação Orientada a Objetos (POO), permitindo que métodos se comportem de maneira diferente dependendo do contexto. Em Java, o polimorfismo ocorre por meio da sobrecarga e da sobrescrita de métodos. Esses dois conceitos permitem flexibilidade no uso de métodos, seja pela alteração de assinaturas (sobrecarga) ou pela redefinição do comportamento herdado (sobrescrita).
O Que é Polimorfismo?
Polimorfismo significa “muitas formas” e refere-se à capacidade de objetos diferentes responderem de maneiras específicas a chamadas de métodos com o mesmo nome. Isso torna possível que uma única interface funcione para várias implementações, dependendo do contexto.
Tipos de Polimorfismo em Java
- Polimorfismo em Tempo de Compilação: Ocorre através da sobrecarga de métodos, onde os métodos possuem o mesmo nome, mas diferentes assinaturas.
- Polimorfismo em Tempo de Execução: Acontece com a sobrescrita de métodos, onde uma subclasse implementa sua própria versão de um método herdado.
Sobrecarga de Métodos (Method Overloading)
A sobrecarga de métodos ocorre quando criamos métodos com o mesmo nome na mesma classe, mas com diferentes listas de parâmetros. A sobrecarga é resolvida em tempo de compilação, pois o compilador escolhe qual método chamar com base no número e tipo dos argumentos passados.
Exemplo de Sobrecarga de Métodos
Aqui, a classe Calculadora
possui métodos somar
que aceitam diferentes tipos de parâmetros:
class Calculadora {
// Método que soma dois inteiros
public int somar(int a, int b) {
return a + b;
}
// Método que soma três inteiros
public int somar(int a, int b, int c) {
return a + b + c;
}
// Método que soma dois números de ponto flutuante
public double somar(double a, double b) {
return a + b;
}
}
public class TesteSobrecarga {
public static void main(String[] args) {
Calculadora calc = new Calculadora();
// Chamando os métodos sobrecarregados
System.out.println(calc.somar(2, 3)); // Chama somar(int, int)
System.out.println(calc.somar(2, 3, 4)); // Chama somar(int, int, int)
System.out.println(calc.somar(2.5, 3.5)); // Chama somar(double, double)
}
}
Saída Esperada
5
9
6.0
Cada chamada ao método somar
usa uma assinatura diferente com base nos argumentos passados.
Sobrescrita de Métodos (Method Overriding)
A sobrescrita ocorre quando uma subclasse redefine um método da superclasse com a mesma assinatura, permitindo que o método na subclasse tenha um comportamento específico. A sobrescrita é resolvida em tempo de execução, permitindo que o método da subclasse seja chamado mesmo quando o objeto é referenciado pela superclasse.
Exemplo de Sobrescrita de Métodos
Vamos usar uma classe Animal
e uma subclasse Cachorro
, onde Cachorro
sobrescreve o método fazerSom
da classe Animal
.
class Animal {
public void fazerSom() {
System.out.println("O animal faz um som");
}
}
class Cachorro extends Animal {
@Override
public void fazerSom() {
System.out.println("O cachorro late");
}
}
public class TesteSobrescrita {
public static void main(String[] args) {
Animal meuAnimal = new Animal();
Animal meuCachorro = new Cachorro();
// Chamadas de método
meuAnimal.fazerSom(); // Chama o método da classe Animal
meuCachorro.fazerSom(); // Chama o método da classe Cachorro devido à sobrescrita
}
}
Saída Esperada
O animal faz um som
O cachorro late
Ao criar um objeto Cachorro
referenciado pela classe Animal
, o método fazerSom
da classe Cachorro
é chamado, devido à sobrescrita.
Diferenças Entre Sobrecarga e Sobrescrita
Aspecto | Sobrecarga de Método | Sobrescrita de Método |
---|---|---|
Resolução | Compilação | Execução |
Classe | Mesma classe ou em subclasses | Em subclasses, herdando de uma superclasse |
Parâmetros | Diferentes assinaturas (quantidade ou tipo) | Mesma assinatura (nome, parâmetros e tipo de retorno) |
Objetivo | Aumentar a flexibilidade de uso de um método | Redefinir o comportamento de um método herdado |
Conclusão
O polimorfismo em Java é essencial para a flexibilidade e escalabilidade do código. Enquanto a sobrecarga permite a reutilização de métodos com diferentes parâmetros, a sobrescrita permite que subclasses forneçam implementações específicas para métodos herdados. Esse recurso torna o código mais adaptável e promove uma estrutura de classes mais organizada e eficiente.