Polimorfismo em Java: Guia Completo com Exemplos Práticos
O que é Polimorfismo em Java?
Polimorfismo é um conceito central na Programação Orientada a Objetos (POO) do Java. Surge quando classes são ligadas por herança, permitindo que uma única interface represente diferentes formas subjacentes. O resultado é que uma chamada de método pode invocar diferentes implementações dependendo do tipo real do objeto em tempo de execução.
Pense em um smartphone que comunica por chamada de voz, texto, imagem ou email. O objetivo – comunicação – é o mesmo, mas cada modo comporta-se diferentemente. Isso é polimorfismo no dia a dia.
O que Você Aprenderá
- Definição de polimorfismo em Java
- Exemplos práticos de POO
- Sobrescrita de método
- Sobrecarga vs. sobrescrita
- Polimorfismo dinâmico (tempo de execução)
- Polimorfismo estático vs. dinâmico
- Palavra-chave
super
Polimorfismo Java em POO: Um Exemplo
Considere uma classe base Conta oferecendo depositar() e sacar(). Duas subclasses, ContaPoupanca e ContaCorrente, herdam esses métodos inalterados porque as operações são idênticas.

Adaptando-se a Requisitos em Mudança
Quando nova funcionalidade – como cheque especial – é requerida, uma subclasse ContaPrivilegiada pode sobrescrever sacar() para prover nova lógica sem tocar subclasses existentes. Isso demonstra vantagem de manutenibilidade do polimorfismo.

Sobrescrita de Método em Java
Sobrescrita ocorre quando subclasse fornece sua própria implementação de método já definido na superclasse. A assinatura do método (nome, parâmetros, tipo de retorno) deve corresponder exatamente.
Regras Principais
- Método sobrescrito pode ter visibilidade mais ampla (ex.:
protectedparapublic) mas nunca mais restrita. - Tipos de retorno devem ser iguais ou covariantes.
Exemplo:
class Medico {
public void tratarPaciente() {
// lógica comum de tratamento
}
}
class Cirurgiao extends Medico {
@Override
public void tratarPaciente() {
// tratamento cirúrgico especializado
}
}
public class Executa {
public static void main(String[] args) {
Medico medico = new Medico();
medico.tratarPaciente(); // executa Medico.tratarPaciente()
Cirurgiao cirurgiao = new Cirurgiao();
cirurgiao.tratarPaciente(); // executa Cirurgiao.tratarPaciente()
}
}
Sobrecarga vs. Sobrescrita
| Sobrecarga de Método | Sobrescrita de Método |
|---|---|
| Mesma classe, mesmo nome, lista de parâmetros diferente. | Método da superclasse redefinido na subclasse com assinatura idêntica. |
Exemplo:void soma(int a, int b); |
Exemplo:class X { int soma() { ... } }
class Y extends X {
@Override int soma() { ... }
} |
Polimorfismo Dinâmico (Tempo de Execução)
Quando referência de superclasse aponta para objeto de subclasse, a JVM resolve a chamada do método em tempo de execução. Isso é polimorfismo verdadeiro em ação.
Medico med = new Cirurgiao(); med.tratarPaciente(); // Executa Cirurgiao.tratarPaciente()
O método real invocado depende do tipo do objeto em tempo de execução, não do tipo da referência.
Polimorfismo Estático vs. Dinâmico
Polimorfismo estático (sobrecarga) é resolvido em tempo de compilação, enquanto polimorfismo dinâmico (sobrescrita) é resolvido em tempo de execução.
| Polimorfismo Estático | Polimorfismo Dinâmico |
|---|---|
| Sobrecarga de método; binding em tempo de compilação. | Sobrescrita de método; binding em tempo de execução. |
Exemplo:void soma(int a, int b); |
Exemplo:Medico m = new Cirurgiao(); |
Usando a Palavra-chave super
Quando subclasse precisa estender método da superclasse, super chama implementação pai antes de adicionar sua própria lógica.
class Cirurgiao extends Medico {
@Override
public void tratarPaciente() {
super.tratarPaciente(); // lógica base
// lógica específica do cirurgião
}
}
Similarmente, super pode acessar campos protected ou public da superclasse.
Exemplo Prático: Herança, Polimorfismo & Super
Copie o código abaixo no seu IDE e observe a saída.
public class Teste {
public static void main(String[] args) {
X x = new X();
Y y = new Y();
y.m2(); // Descomente para ver efeitos de herança
// x.m1();
// y.m1();
// x = y; // referência pai para objeto filho
// x.m1();
// y.a = 10; // erro: a é private
}
}
class X {
private int a;
int b;
public void m1() {
System.out.println("Este é método m1 da classe X");
}
}
class Y extends X {
int c;
@Override
public void m1() {
System.out.println("Este é método m1 da classe Y");
}
public void m2() {
super.m1();
System.out.println("Este é método m2 da classe Y");
}
}
Principais Conclusões
- Polimorfismo permite objetos assumirem múltiplas formas através de herança.
- Sobrescrita de método muda comportamento em subclasses mantendo mesma assinatura.
- Polimorfismo dinâmico resolve chamadas de método em tempo de execução, habilitando código flexível.
- Polimorfismo estático (sobrecarga) é em tempo de compilação, enquanto dinâmico é em tempo de execução.
- Palavra-chave
superpermite subclasses invocarem métodos pai ou acessarem membros protected.
Java
- Dominando Polimorfismo em Java: Conceitos, Exemplos e Boas Práticas
- Classes Abstratas em C#: Tutorial Prático com Exemplos de Código
- Entendendo Interfaces em C#: Definição, Exemplo e Uso Prático
- Método Java String length(): Como Obter o Tamanho de uma String (Exemplo)
- Entendendo Java String.charAt(): Sintaxe, Tipo de Retorno, Exceções e Exemplo Prático
- Método Java String.contains(): Como Verificar Substrings – Exemplos Práticos
- Dominando Java String.endsWith(): Como Verificar Sufixos de String com Exemplos
- Java Static Explicado: Variáveis, Métodos e Blocos – Exemplos Práticos
- Interface vs Classe Abstrata em Java: Como Escolher a Abstração Certa
- Lendo Arquivos em Java com BufferedReader – Guia Prático com Exemplos