Java POO Intermediário
Polimorfismo
Polimorfismo é a capacidade de um objeto ser referenciado por diferentes tipos, permitindo que uma mesma chamada de método produza comportamentos distintos dependendo do objeto real. Em Java, isso é possível porque uma variável de um tipo superclasse pode referenciar objetos de subclasses.
O despacho dinâmico (dynamic dispatch) é o mecanismo pelo qual a JVM decide, em tempo de execução, qual implementação do método será executada, baseada no tipo real do objeto, e não no tipo da variável. Isso permite escrever código genérico que funciona com qualquer subclasse.
Para verificar o tipo real de um objeto, usamos instanceof. Desde Java 16, o pattern matching para instanceof permite declarar uma variável já convertida no mesmo comando, eliminando a necessidade de casting explícito. Quando precisamos acessar membros específicos de uma subclasse, podemos fazer casting explícito, mas isso só é seguro se o objeto for realmente daquele tipo.
Pontos-chave
- Uma referência de superclasse pode apontar para objetos de qualquer subclasse.
- O método executado é escolhido em tempo de execução pelo tipo real do objeto (despacho dinâmico).
instanceofcom pattern (Java 16+) permite testar e converter em uma única expressão.- Casting explícito é necessário para acessar membros específicos da subclasse, mas pode lançar
ClassCastExceptionse o tipo estiver errado. - Use
@Overridepara garantir que você está sobrescrevendo corretamente um método da superclasse.
// Exemplo de polimorfismo em Java
abstract class Animal {
abstract void emitirSom();
}
class Cachorro extends Animal {
@Override
void emitirSom() {
System.out.println("Au au!");
}
void abanarRabo() {
System.out.println("Cachorro abanando o rabo...");
}
}
class Gato extends Animal {
@Override
void emitirSom() {
System.out.println("Miau!");
}
}
public class PolimorfismoExemplo {
public static void main(String[] args) {
// Referência de superclasse apontando para objetos de subclasses
Animal a1 = new Cachorro();
Animal a2 = new Gato();
// Despacho dinâmico: o método chamado depende do tipo real
a1.emitirSom(); // Au au!
a2.emitirSom(); // Miau!
// instanceof com pattern (Java 16+)
if (a1 instanceof Cachorro c) {
c.abanarRabo(); // método específico de Cachorro
}
// Casting explícito (seguro após verificação)
if (a2 instanceof Gato) {
Gato g = (Gato) a2;
g.emitirSom(); // Miau!
}
}
}