Animal
que denota animais e criar um método nela voice
- “ voz ”:
public class Animal {
public void voice() {
System.out.println("Voice!");
}
}
Embora tenhamos apenas começado a escrever o programa, você provavelmente pode ver o problema potencial: há muitos animais no mundo, e todos eles “falam” de maneira diferente: gatos miam, patos grasnam, cobras sibilam. Nosso objetivo é simples: evitar a criação de vários métodos para votar. Em vez de criar métodos voiceCat()
para miar, voiceSnake()
assobiar, etc., queremos voice()
que a cobra sibile, o gato mie e o cachorro latir quando o método for chamado. Podemos conseguir isso facilmente usando o mecanismo de substituição de método (Override em Java) . A Wikipedia fornece a seguinte explicação do termo “substituição”: A substituição de método na programação orientada a objetos é um dos recursos de uma linguagem de programação que permite que uma subclasse ou classe filha forneça uma implementação específica de um método já implementado em uma das superclasses ou classes parentais. É, em geral, correto. A substituição permite que você pegue um método de uma classe pai e escreva sua própria implementação desse método em cada classe descendente. A nova implementação irá “substituir” o pai na classe filha. Vamos ver como isso fica com um exemplo. Vamos criar 4 classes sucessoras para nossa classe Animal
:
public class Bear extends Animal {
@Override
public void voice() {
System.out.println("Р-р-р!");
}
}
public class Cat extends Animal {
@Override
public void voice() {
System.out.println("Meow!");
}
}
public class Dog extends Animal {
@Override
public void voice() {
System.out.println("Woof!");
}
}
public class Snake extends Animal {
@Override
public void voice() {
System.out.println("Ш-ш-ш!");
}
}
Um pequeno truque para o futuro: para substituir os métodos da classe pai, vá para o código da classe descendente no Intellij IDE a, pressione Ctrl+O e selecione “ Substituir métodos... ” no menu. Acostume-se a usar teclas de atalho desde o início, isso irá acelerar a escrita de programas! Para definir o comportamento que queríamos, fizemos algumas coisas:
- Criamos um método em cada classe descendente com o mesmo nome do método da classe pai.
-
Dissemos ao compilador que nomeamos o método da mesma forma que na classe pai por um motivo: queríamos substituir seu comportamento. Para esta “mensagem” ao compilador, colocamos uma anotação @Override no método .
A anotação @Override colocada acima de um método diz ao compilador (e aos programadores que leem seu código também): “Está tudo bem, isso não é um erro ou esquecimento meu. Lembro que esse método já existe e quero substituí-lo." - Escrevemos a implementação necessária para cada classe descendente. Quando chamada, uma cobra
voice()
deve sibilar, um urso deve rosnar, etc.
public class Main {
public static void main(String[] args) {
Animal animal1 = new Dog();
Animal animal2 = new Cat();
Animal animal3 = new Bear();
Animal animal4 = new Snake();
animal1.voice();
animal2.voice();
animal3.voice();
animal4.voice();
}
}
Saída do console: Uau! Miau! Rrr! Shhh! Ótimo, tudo funciona como deveria! Criamos 4 variáveis de referência da classe pai Animal
e as atribuímos a 4 objetos diferentes das classes descendentes. Como resultado, cada objeto se comporta de maneira diferente. Para cada uma das classes descendentes, o método substituído voice()
substituiu o método “nativo” voice()
da classe Animal
(que simplesmente envia “Voice!” para o console). A substituição tem uma série de limitações:
-
O método substituído deve ter os mesmos argumentos do método pai.
Se um método
voice
em uma classe pai aceita como inputString
, o método substituído na classe filha também deve aceitar como inputString
, caso contrário o compilador gerará um erro:public class Animal { public void voice(String s) { System.out.println("Voice! " + s); } } public class Cat extends Animal { @Override//error! public void voice() { System.out.println("Meow!"); } }
-
O método substituído deve ter o mesmo tipo de retorno do método pai.
Caso contrário, receberemos um erro de compilação:
public class Animal { public void voice() { System.out.println("Voice!"); } } public class Cat extends Animal { @Override public String voice() { //error! System.out.println("Meow!"); return "Meow!"; } }
-
O modificador de acesso de um método substituído também não pode diferir do “original”:
public class Animal { public void voice() { System.out.println("Voice!"); } } public class Cat extends Animal { @Override private void voice() { //error! System.out.println("Meow!"); } }
voice()
para todos em vez de um monte de métodos voiceDog()
, voiceCat()
etc.
GO TO FULL VERSION