No entiendo por qué no hay herencia en las anotaciones de Java, al igual que las clases de Java. Creo que sería muy útil.
Por ejemplo: quiero saber si una anotación dada es un validador. Con la herencia, podría navegar reflexivamente por las superclases para saber si esta anotación se extiende a ValidatorAnnotation
. De lo contrario, ¿cómo puedo lograr esto?
Entonces, ¿alguien puede darme una razón para esta decisión de diseño?
java
inheritance
annotations
sinuhepop
fuente
fuente
java.lang.annotation.Annotation
, es decir, cualquier anotación lo esinstanceof
, aunque este hecho no se declara explícitamente.Respuestas:
Sobre la razón por la que no se diseñó de esa manera, puede encontrar la respuesta en las Preguntas frecuentes de diseño de JSR 175 , donde dice:
Entonces, sí, supongo, la razón es solo KISS. De todos modos, parece que este problema (junto con muchos otros) se está estudiando como parte de JSR 308 , e incluso puede encontrar un compilador alternativo con esta funcionalidad ya desarrollada por Mathias Ricken .
fuente
Las anotaciones extensibles agregarían efectivamente la carga de especificar y mantener otro sistema de tipos. Y este sería un sistema de tipos bastante único, por lo que no podría simplemente aplicar un paradigma de tipo OO.
Piense detenidamente en todos los problemas cuando introduzca el polimorfismo y la herencia en una anotación (por ejemplo, ¿qué sucede cuando la subanotación cambia las especificaciones de la metaanotación como la retención?)
¿Y toda esta complejidad añadida para qué caso de uso?
¿Quiere saber si una anotación dada pertenece a una categoría?
Prueba esto:
Como puede ver, puede agrupar y clasificar fácilmente las anotaciones sin dolor excesivo utilizando las facilidades proporcionadas.
Entonces, KISS es la razón para no introducir un sistema de tipo meta-tipo en el lenguaje Java.
[ps editar]
Utilicé la cadena simplemente para demostración y en vista de una anotación meta abierta. Para su propio proyecto dado, obviamente puede usar una enumeración de tipos de categoría y especificar múltiples categorías ("herencia múltiple") para una anotación dada. Tenga en cuenta que los valores son completamente falsos y solo con fines de demostración:
fuente
@Target(ElementType.ANNOTATION_TYPE) @Retention(RetentionPolicy.RUNTIME) @interface C {}; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @C public @interface F {} class a{ @F public void S() {} } @Test public void blahTest() throws NoSuchMethodException { Method m = a.class.getMethod("S"); System.out.println(m.isAnnotationPresent(C.class)); }
En cierto sentido, ya lo tiene con Anotaciones: meta Anotaciones. Si anota una anotación con metainformación, en muchos aspectos es equivalente a extender una interfaz adicional. Las anotaciones son interfaces, por lo que el polimorfismo realmente no entra en juego, y dado que son de naturaleza estática, no puede haber un despacho dinámico en tiempo de ejecución.
En el ejemplo de su validador, podría simplemente en la anotación obtener el tipo anotado y ver si tiene una metaanotación del validador.
El único caso de uso en el que podría ver que la herencia ayudaría es si quisieras poder obtener la anotación por supertipo, pero eso agregaría una gran cantidad de complejidad, porque un método o tipo dado puede tener dos de esas anotaciones, lo que significa que una matriz debería ser devuelta en lugar de un solo objeto.
Así que creo que la respuesta final es que los casos de uso son esotéricos y complican los casos de uso más estándar, lo que hace que no valga la pena.
fuente
Los diseñadores del soporte de anotaciones de Java hicieron una serie de "simplificaciones" en detrimento de la comunidad de Java.
Ningún subtipo de anotaciones hace que muchas anotaciones complejas sean innecesariamente feas. Uno no puede simplemente tener un atributo dentro de una anotación que pueda contener una de tres cosas. Uno debe tener tres atributos separados, lo que confunde a los desarrolladores y requiere la validación del tiempo de ejecución para garantizar que solo se use uno de los tres.
Solo una anotación de un tipo dado por sitio. Esto ha llevado a un patrón de anotación de colección completamente innecesario. @Validation y @Validations, @Image y @Images, etc.
El segundo se está remediando en Java 8, pero es demasiado tarde. Se han escrito muchos marcos basados en lo que era posible en Java 5 y ahora estas verrugas API están aquí para quedarse durante mucho tiempo.
fuente
Puede que tarde tres años en responder a esta pregunta, pero me pareció interesante porque me encontré en el mismo lugar. Aquí está mi opinión al respecto. Puede ver las anotaciones como enumeraciones. Proporcionan un tipo de información unidireccional: úsela o piérdala.
Tuve una situación en la que quería simular GET, POST, PUT y DELETE en una aplicación web. Tenía muchas ganas de tener una "super" anotación que se llamaba "HTTP_METHOD". Más tarde me di cuenta de que no importaba. Bueno, tuve que conformarme con usar un campo oculto en el formulario HTML para identificar DELETE y PUT (porque POST y GET estaban disponibles de todos modos).
En el lado del servidor, busqué un parámetro de solicitud oculto con el nombre, "_method". Si el valor era PUT o DELETE, anula el método de solicitud HTTP asociado. Dicho esto, no importaba si necesitaba o no extender una anotación para hacer el trabajo. Todas las anotaciones se veían iguales, pero se trataban de manera diferente en el lado del servidor.
Entonces, en su caso, suelte el picor para extender las anotaciones. Trátelos como 'marcadores'. "Representan" cierta información y no necesariamente "manipulan" cierta información.
fuente
Una cosa que se me ocurre es la posibilidad de tener múltiples anotaciones. Entonces podría agregar un validador y una anotación más específica en el mismo lugar. Pero podría estar equivocado :)
fuente
Nunca pensé en eso, pero ... parece que tienes razón, no hay ningún problema con el recurso de herencia de anotaciones (al menos no veo el problema con él).
Acerca de su ejemplo con la anotación 'validador' : puede explotar el enfoque de 'metaanotación' . Es decir, aplica metaanotaciones particulares a toda la interfaz de anotaciones.
fuente
el mismo problema que tengo No puedes. Me "discipliné" a mí mismo para escribir propiedades en anotaciones para respetar algunos estándares, así que afuera, cuando obtienes una anotación, puedes "oler" qué tipo de anotación es por las propiedades que tiene.
fuente