Sobrescrita de Método (@Override)
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 22 de 87.
A sobrescrita de método (method overriding) permite que uma subclasse forneça sua própria implementação de um método que já está definido em sua classe pai. É assim que as classes filhas personalizam o comportamento herdado para atender às suas necessidades específicas.
Quando você sobrescreve um método, a versão da subclasse substitui completamente a versão da classe pai para objetos dessa subclasse. O método deve ter o mesmo nome, tipo de retorno e parâmetros que o método pai:
public class Animal {
public void makeSound() {
System.out.println("Some generic sound");
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof!");
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow!");
}
}A anotação @Override informa ao compilador que você pretende sobrescrever um método pai. Embora opcional, é fortemente recomendada porque o compilador capturará erros se você acidentalmente escrever incorretamente o nome do método ou usar parâmetros errados:
@Override
public void makeSound() { } // Correto - o compilador verifica isso
public void makesound() { } // Erro de digitação! Cria um novo método em vez de sobrescreverQuando você chama um método sobrescrito, o Java executa a versão que pertence ao tipo real do objeto:
Dog dog = new Dog();
dog.makeSound(); // Saída: Woof!
Cat cat = new Cat();
cat.makeSound(); // Saída: Meow!Lembre-se da lição anterior que você pode usar super.methodName() dentro de um método sobrescrito se você ainda quiser incluir o comportamento do pai junto com seu novo código.
Desafio
FácilVamos construir um sistema de notificação que demonstra como as subclasses podem sobrescrever métodos da classe pai para fornecer seu próprio comportamento especializado. Você verá como a anotação @Override ajuda a captar erros e como cada subclasse pode personalizar métodos herdados.
Você criará três arquivos para organizar seu código:
Notification.java: Crie a classe pai que representa uma notificação genérica. Ela deve ter:- Um campo privado para a
message(String) - Um construtor que aceita a mensagem
- Um método
getMessage()que retorna a mensagem - Um método
send()que imprime:Sending notification: [message]
- Um campo privado para a
EmailNotification.java: Crie uma subclasse que estende Notification e personaliza como as notificações são enviadas via e-mail:- Um campo privado para o endereço de e-mail do
recipient(String) - Um construtor que recebe tanto a mensagem quanto o destinatário, usando
super(message)para a parte da classe pai - Sobrescreva o método
send()usando a anotação@Overridepara imprimir:Emailing [recipient]: [message]
- Um campo privado para o endereço de e-mail do
Main.java: Demonstre como o mesmo nome de método produz comportamentos diferentes dependendo do tipo de objeto. Você receberá duas entradas: uma mensagem e um endereço de e-mail. Crie tanto uma Notification regular quanto uma EmailNotification com a mesma mensagem, então chamesend()em cada uma para ver as diferentes saídas.
Você receberá duas entradas: a mensagem (String) e o endereço de e-mail do destinatário (String).
Sua saída deve mostrar duas linhas - primeiro do método send() da classe pai, depois da versão sobrescrita em EmailNotification. Isso demonstra como a sobrescrita de métodos permite que as subclasses substituam o comportamento herdado por sua própria implementação.
Folha de consulta
A sobrescrita de método (method overriding) permite que uma subclasse forneça sua própria implementação de um método que já foi definido em sua classe pai. O método sobrescrito deve ter o mesmo nome, tipo de retorno e parâmetros que o método pai.
public class Animal {
public void makeSound() {
System.out.println("Some generic sound");
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof!");
}
}A anotação @Override é opcional, mas fortemente recomendada. Ela informa ao compilador que você pretende sobrescrever um método pai, ajudando a detectar erros como nomes de métodos digitados incorretamente ou parâmetros incorretos:
@Override
public void makeSound() { } // Correto - o compilador verifica isso
public void makesound() { } // Erro de digitação! Cria um novo método em vez de sobrescreverAo chamar um método sobrescrito, o Java executa a versão que pertence ao tipo real do objeto:
Dog dog = new Dog();
dog.makeSound(); // Output: Woof!
Cat cat = new Cat();
cat.makeSound(); // Output: Meow!Você pode usar super.methodName() dentro de um método sobrescrito para incluir o comportamento do pai junto com seu novo código.
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Ler as entradas
String message = scanner.nextLine();
String recipient = scanner.nextLine();
// TODO: Criar um objeto Notification com a mensagem
// TODO: Criar um objeto EmailNotification com a mensagem e o destinatário
// TODO: Chamar send() no objeto Notification
// TODO: Chamar send() no objeto EmailNotification
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Iterator