¿Deberíamos @ anular la implementación del método de una interfaz?

432

¿Se debe anotar un método que implemente un método de interfaz @Override?

El javadoc de la Overrideanotación dice:

Indica que una declaración de método tiene la intención de anular una declaración de método en una superclase. Si un método se anota con este tipo de anotación pero no anula un método de superclase, los compiladores deben generar un mensaje de error.

No creo que una interfaz sea técnicamente una superclase. ¿O es eso?

Question Elaboration

Benno Richters
fuente
55
wow esta pregunta podría ser más corta, pero es la pregunta que necesitaba. Gracias
Dan Rosenstark
1
No puedo encontrar el reemplazo para el artículo @Override (Oracle movió los viejos blogs de Sun recientemente). ¿Sabes cómo encontrarlo?
Bill the Lizard
44
Ya deberíamos tener una anotación @Implement (s) (2015). ¡Eso aclarará las cosas!
Alex
3
a estas alturas (2015) ¿deberíamos usar @Override con java 8?
Lorenzo Sciuto

Respuestas:

305

Debería usar @Override siempre que sea posible. Evita que se cometan errores simples. Ejemplo:

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

Esto no se compila porque no se anula correctamente public boolean equals(Object obj).

Lo mismo se aplicará a los métodos que implementan una interfaz ( 1.6 y superior solamente ) o anulan el método de una Súper clase.

jjnguy
fuente
150
Tenga en cuenta que no puede agregar la anotación @Override a un método que implementa una interfaz en Java 5: genera un error. Está permitido en Java 6.
Bill Michell
17
Um, no, no lo hace. De hecho, Eclipse inserta automáticamente @Override al completar métodos que implementan una interfaz.
jjnguy
14
-1 hasta que la respuesta incluya una mención sobre el comportamiento diferente de Java 1.5 a 1.6 con respecto a la implementación de un método de interfaz. Solo porque he visto que es un aspecto confuso para las personas y realmente merece una mención.
Grundlefleck el
2
Si eclipse se queja, actualice ur jdk a> 1.5 y cambie el nivel de cumplimiento del compilador a 1.6 o 1.7. Para hacer eso, haga clic derecho en su proyecto-> propiedades-> compilador Java y seleccione uno que sea superior a 1.5.
Rose
1
¿Alguien puede pensar en un ejemplo que realmente justifique la respuesta (implementando interfaces en lugar de anular los métodos básicos)? Una gran ventaja para mí es que ayuda a establecer las expectativas de los lectores sobre cómo y por qué un método en particular podría usarse.
Joe Lee-Moyet
103

Creo que el comportamiento de javac ha cambiado: con 1.5 prohibió la anotación, con 1.6 no. La anotación proporciona una verificación adicional en tiempo de compilación, por lo que si está utilizando 1.6, lo haría.

Jon Skeet
fuente
1
¿Qué es el cheque extra?
Michael Carman
17
@ Michael Puedes notar si alguna interfaz se ha eliminado.
Sanghyun Lee
68

Siempre debe anotar métodos con @Overridesi está disponible.

En JDK 5, esto significa anular métodos de superclases, en JDK 6 y 7 significa anular métodos de superclases e implementar métodos de interfaces. La razón, como se mencionó anteriormente, es que permite que el compilador detecte errores donde cree que está anulando (o implementando) un método, pero en realidad está definiendo un nuevo método (firma diferente).

El ejemplo equals(Object)vs. equals(YourObject)es un ejemplo estándar, pero se puede hacer el mismo argumento para implementaciones de interfaz.

Me imagino que la razón por la que no es obligatorio anotar la implementación de métodos de interfaces es que JDK 5 marcó esto como un error de compilación. Si JDK 6 hiciera esta anotación obligatoria, rompería la compatibilidad con versiones anteriores.

No soy un usuario de Eclipse, pero en otros IDEs (IntelliJ), la @Overrideanotación solo se agrega al implementar métodos de interfaz si el proyecto se configura como un proyecto JDK 6+. Me imagino que Eclipse es similar.

Sin embargo, hubiera preferido ver una anotación diferente para este uso, tal vez una @Implementsanotación.

GKelly
fuente
11

JDK 5.0 no le permite usar @Overrideanotaciones si está implementando un método declarado en la interfaz (su error de compilación), pero JDK 6.0 lo permite. Entonces, puede configurar su preferencia de proyecto de acuerdo con sus requisitos.

Guerrero silencioso
fuente
4

Si una clase concreta no anula un método abstracto, el uso @Overridepara la implementación es una cuestión abierta ya que el compilador le advertirá invariablemente de cualquier método no implementado. En estos casos, se puede argumentar que resta valor a la legibilidad: es más cosas para leer en su código y, en menor grado, se llama @Overridey no @Implement.

juanchito
fuente
3

Reemplazar sus propios métodos heredados de sus propias clases generalmente no se romperá en las refactorizaciones utilizando un ide. Pero si anula un método heredado de una biblioteca, se recomienda usarlo. Si no lo hace, a menudo no obtendrá ningún error en un cambio posterior de la biblioteca, sino un error bien oculto.

Arne Burmeister
fuente
3

No es un problema con JDK. En Eclipse Helios, permite la anotación @Override para los métodos de interfaz implementados, cualquiera que sea JDK 5 o 6. En cuanto a Eclipse Galileo, la anotación @Override no está permitida, cualquiera que sea JDK 5 o 6.

lwpro2
fuente
2

Para mí, muchas veces esta es la única razón por la que algunos códigos requieren que Java 6 se compile. No estoy seguro si vale la pena.

Fabian Steeg
fuente
2

Al leer el javadoc en java8, puede encontrar lo siguiente en la declaración de anulación de interfaz:

Si se anota un método con este tipo de anotación, se requiere que los compiladores generen un mensaje de error a menos que se cumpla al menos una de las siguientes condiciones:

  • El método anula o implementa un método declarado en un supertipo.
  • El método tiene una firma que es equivalente a la de cualquier método público declarado en {@linkplain Object}.

Entonces, al menos en java8, debe usar @Override en una implementación de un método de interfaz.

Zhao Pengfei
fuente
1

Eclipse agregará la @Overrideanotación cuando le diga que "genere métodos no implementados" durante la creación de una clase que implemente una interfaz.

savetheclocktower
fuente
1

El problema con la inclusión de @Overridees que te hace pensar que olvidaste llamar al super.theOverridenMethod()método, lo cual es muy confuso . Esto debería ser claro como el cristal. Quizás Java debería ofrecer un @Interfacepara ser utilizado aquí. Oh, bueno, otra peculiaridad de Java a medias ...

spujia
fuente
3
Llamar a un super, cuando no está implementando una interfaz, no es algo que siempre necesita o quiere hacer. A veces, está agregando funcionalidad, por lo que lo llama. Otras veces, está reemplazando la funcionalidad, por lo que no la llama. Un autor de API debe documentar si se basa en la funcionalidad interna o no y crear un contrato documentado sobre cómo la clase se puede extender adecuadamente.
lilbyrdie
1

En java 6 y versiones posteriores, puede usar @Overrideun método para implementar una interfaz.

Pero no creo que tenga sentido: anular significa que tiene un método en la superclase y lo está implementando en la subclase.

Si está implementando una interfaz, creo que deberíamos usar @Implemento algo más, pero no el @Override.

ZhaoGang
fuente
0

Para la interfaz, el uso de @Override provocó un error de compilación. Entonces, tuve que eliminarlo.

El mensaje de error fue " The method getAllProducts() of type InMemoryProductRepository must override a superclass method".

También se lee " One quick fix available: Remove @Override annotation."

Estaba en Eclipse 4.6.3, JDK 1.8.0_144.

Park JongBum
fuente
0

Si la clase que está implementando interfacees una abstractclase, @Overridees útil para garantizar que la implementación sea para un interfacemétodo; sin @Overrideuna abstractclase simplemente se compilaría bien incluso si la firma del método de implementación no coincide con el método declarado en interface; el interfacemétodo no coincidente permanecería como no implementado. El documento de Java citado por @Zhao

El método anula o implementa un método declarado en un supertipo

se refiere claramente a una abstractsuperclase; una interfaceno puede ser llamado el supertipo. Por lo tanto, @Overridees redundante y no es sensible para interfaceimplementaciones de métodos en clases concretas.

Madhu
fuente