Devemos @ Substituir a implementação do método de uma interface?

432

Um método que implementa um método de interface deve ser anotado @Override?

O javadoc da Overrideanotação diz:

Indica que uma declaração de método se destina a substituir uma declaração de método em uma superclasse. Se um método é anotado com esse tipo de anotação, mas não substitui um método de superclasse, os compiladores são necessários para gerar uma mensagem de erro.

Eu não acho que uma interface seja tecnicamente uma superclasse. Ou é?

Question Elaboration

Benno Richters
fonte
5
uau, essa pergunta pode ser mais curta, mas é a pergunta que eu precisava. Obrigado
Dan Rosenstark
1
Não consigo encontrar o substituto para o artigo @Override (a Oracle mudou recentemente os antigos blogs da Sun). Você sabe como encontrá-lo?
Bill o Lagarto
4
Devemos ter uma anotação de @Implement (s) até agora (2015). Isso vai esclarecer as coisas!
1937 Alex
3
até agora (2015), devemos usar o @Override com o java 8?
Lorenzo Sciuto

Respostas:

305

Você deve usar @Override sempre que possível. Impede que erros simples sejam cometidos. Exemplo:

class C {
    @Override
    public boolean equals(SomeClass obj){
        // code ...
    }
}

Isso não compila porque não substitui corretamente public boolean equals(Object obj).

O mesmo vale para métodos que implementam uma interface ( somente 1.6 e acima ) ou substituem o método de uma classe Super.

jjnguy
fonte
150
Observe que você não pode adicionar a anotação @Override a um método que implementa uma interface no Java 5 - isso gera um erro. É permitido no Java 6. #
Bill Michell
17
Hum, não, não faz. De fato, o Eclipse insere automaticamente o @Override ao preencher métodos que implementam uma interface.
jjnguy
14
-1 até a resposta incluir uma menção sobre o comportamento diferente do Java 1.5 a 1.6 com relação à implementação de um método de interface. Só porque eu vi que isso é um aspecto confuso para as pessoas e realmente merece uma menção.
Grundlefleck
2
Se o eclipse estiver reclamando, atualize o ur jdk para> 1.5 e altere o nível de conformidade do compilador para 1.6 ou 1.7. Para fazer isso, clique com o botão direito do mouse em seu projeto-> propriedades-> compilador Java e selecione um que seja maior que 1,5.
Rose
1
Alguém pode pensar em um exemplo que realmente justifique a resposta (implementando interfaces em vez de substituir os métodos básicos)? Uma grande vantagem para mim é que ela ajuda as expectativas dos leitores de como e por que método específico pode ser usado.
Joe Lee-Moyet
103

Acredito que o comportamento do javac mudou - com 1,5 proibiu a anotação e com 1,6 não. A anotação fornece uma verificação extra em tempo de compilação; portanto, se você estiver usando o 1.6, eu a utilizarei.

Jon Skeet
fonte
1
Qual é o cheque extra?
Michael Carman
17
@ Michael Você pode perceber se alguma interface foi excluída.
Sanghyun Lee 27/02/12
68

Você sempre deve anotar métodos com, @Overridese estiverem disponíveis.

No JDK 5, isso significa substituir métodos de superclasses, no JDK 6 e 7 significa substituir métodos de superclasses e implementar métodos de interfaces. O motivo, como mencionado anteriormente, é que permite ao compilador detectar erros nos quais você acha que está substituindo (ou implementando) um método, mas na verdade está definindo um novo método (assinatura diferente).

O exemplo equals(Object)vs. equals(YourObject)é um caso padrão em questão, mas o mesmo argumento pode ser feito para implementações de interface.

Eu imagino que a razão pela qual não é obrigatório anotar métodos de implementação de interfaces é que o JDK 5 sinalizou isso como um erro de compilação. Se o JDK 6 tornasse essa anotação obrigatória, a compatibilidade seria retroativa.

Não sou usuário do Eclipse, mas em outros IDEs (IntelliJ), a @Overrideanotação é adicionada apenas ao implementar métodos de interface se o projeto estiver definido como um projeto JDK 6+. Eu imaginaria que o Eclipse é semelhante.

No entanto, eu preferiria ver uma anotação diferente para esse uso, talvez uma @Implementsanotação.

GKelly
fonte
11

O JDK 5.0 não permite que você use @Overrideanotações se estiver implementando o método declarado na interface (erro de compilação), mas o JDK 6.0 permite. Assim, você pode configurar sua preferência de projeto de acordo com sua exigência.

Guerreiro Silencioso
fonte
4

Se uma classe concreta não está substituindo um método abstrato, o uso @Overridepara implementação é um assunto em aberto, pois o compilador sempre avisa sobre quaisquer métodos não implementados. Nesses casos, pode-se argumentar que isso prejudica a legibilidade - é mais coisas para ler no seu código e, em menor grau, é chamado @Overridee não @Implement.

juanchito
fonte
3

Substituir seus próprios métodos herdados de suas próprias classes normalmente não afeta as refatorações usando um ide. Mas se você substituir um método herdado de uma biblioteca, é recomendável usá-lo. Caso contrário, muitas vezes você não receberá nenhum erro em uma alteração posterior da biblioteca, mas um bug bem escondido.

Arne Burmeister
fonte
3

Não é um problema com o JDK. No Eclipse Helios, ele permite a anotação @Override para métodos de interface implementados, o que for JDK 5 ou 6. Como no Eclipse Galileo, a anotação @Override não é permitida, o que for JDK 5 ou 6.

lwpro2
fonte
2

Para mim, muitas vezes esse é o único motivo pelo qual alguns códigos exigem que o Java 6 seja compilado. Não tenho certeza se vale a pena.

Fabian Steeg
fonte
2

Lendo o javadoc em java8, você pode encontrar o seguinte na declaração da interface Override:

Se um método for anotado com esse tipo de anotação, os compiladores serão necessários para gerar uma mensagem de erro, a menos que pelo menos uma das seguintes condições seja mantida:

  • O método substitui ou implementa um método declarado em um supertipo.
  • O método tem uma assinatura equivalente à substituição de qualquer método público declarado em {@linkplain Object}.

Portanto, pelo menos no java8, você deve usar o @Override na implementação de um método de interface.

Zhao Pengfei
fonte
1

O próprio Eclipse adicionará a @Overrideanotação quando você instruir a "gerar métodos não implementados" durante a criação de uma classe que implementa uma interface.

savetheclocktower
fonte
1

O problema de incluir o @Overrideé que isso faz você pensar que esqueceu de chamar o super.theOverridenMethod()método, o que é muito confuso . Isso deve ficar claro como cristal. Talvez o Java deva oferecer um @Interfacepara ser usado aqui. Oh, bem, mais uma peculiaridade Java meia-boca ...

spujia
fonte
3
Chamar um super, quando não está implementando uma interface, não é algo que você sempre precisa ou deseja fazer. Às vezes, você está adicionando funcionalidade - assim você chama. Outras vezes, você substitui a funcionalidade para não chamá-la. Um autor da API deve documentar se depende ou não da funcionalidade interna e criar um contrato documentado sobre como a classe pode ser adequadamente estendida.
lilbyrdie
1

No java 6 e versões posteriores, você pode usar @Overrideum método para implementar uma interface.

Mas não acho que faça sentido: substituir significa que você tem um método na superclasse e está implementando-o na subclasse.

Se você está implementando uma interface, acho que devemos usar @Implementou algo mais, mas não o @Override.

ZhaoGang
fonte
0

Para a interface, usar @Override causou erro de compilação. Então, eu tive que removê-lo.

A mensagem de erro foi " The method getAllProducts() of type InMemoryProductRepository must override a superclass method".

Também leu " One quick fix available: Remove @Override annotation."

Estava no Eclipse 4.6.3, JDK 1.8.0_144.

Park JongBum
fonte
0

Se a classe que está implementando o interfacefor uma abstractclasse, @Overrideé útil para garantir que a implementação seja para um interfacemétodo; sem @Overrideuma abstractclasse seria apenas compilar bem mesmo se a assinatura método de implementação não corresponde ao método declarado no interface; o interfacemétodo incompatível permaneceria como não implementado. O documento Java citado por @Zhao

O método substitui ou implementa um método declarado em um supertipo

está claramente se referindo a uma abstractsuper classe; um interfacenão pode ser chamado de supertipo. Portanto, @Overrideé redundante e não é sensato para interfaceimplementações de métodos em classes concretas.

Madhu
fonte