¿La interfaz como etiquetas es una mala práctica en Java OO?
Pregunta
Durante el análisis de ciertos archivos xml, me encuentro con una situación en la que tengo que usar la interfaz como etiquetas para identificar que ciertas etiquetas pertenecen a cierta categoría, por ejemplo, creé una interfaz Etiqueta para identifique que estas clases se usan para representar etiquetas xml y ContainableTag para señalar que ciertas etiquetas pueden ser una de las etiquetas secundarias de algunas etiquetas.
Luego me encuentro con esta página: http://xahlee.org/java-a -day / interface.html (Busque la sesión " Interfaz como etiquetas "). Dice:
La esencia del problema es que es una pieza de irrelevancia matemática en el idioma. Como mecanismo de etiquetado en un idioma, para lo posible beneficiarse de la ingeniería de software perspectiva, entonces no debería ser diseñado como parte de la clase Interfaz, ya que el concepto de etiquetado y concepto de programación interfaz, son semánticamente dispares.
Entonces, ¿la interfaz como etiquetas es necesariamente una mala práctica? Como programador de Java, ¿tenemos otras alternativas?
Solución
Las interfaces como marcadores han sido reemplazadas en gran medida por el mecanismo de anotación en Java 5 o posterior. Le permiten agregar metadatos arbitrarios. Si sus interfaces están vacías y solo sirven para actuar como marcadores de clase, entonces debería usar anotaciones en su lugar.
Otros consejos
Si bien las anotaciones pueden proporcionar una alternativa para lo que logran las interfaces de marcador, solo están disponibles en Java y no se integran bien con IDE: también uso interfaces de marcador para etiquetar conceptos relacionados en mi proyecto, y luego puedo usar el tipo navegador de jerarquía para encontrar todos los miembros (supongo que esto será eventualmente compatible con IDE principales para anotaciones pronto).
En cuanto al artículo que menciona, no veo el punto de argumentar que si una clase sintáctica / estructuralmente "cumple" una interfaz, esa interfaz puede / debe aplicarse automáticamente a la clase (" Cualquier clase puede declararla [RandomAccess] como una interfaz ... "). Eso es pensar al revés, en mi opinión.
Yo diría que los lugares, donde se usa dicha interfaz de marcador en una declaración de 'instancia de', usan lógica invertida, pero mientras esté atrapado dentro de un lenguaje sin herencia, aspectos y anotaciones múltiples, no veo nada mejor manera de lograr esto sin salir del lenguaje base.
También tenga en cuenta que este argumento irreal sobre una interfaz vacía que siempre es aplicable también podría aplicarse a las anotaciones.
Las anotaciones no son necesariamente lo que quieres. Las interfaces de etiquetado son una forma de trabajar una propiedad de un tipo en el tipo mismo. Por ejemplo, si está a punto de comenzar a escribir código con este aspecto:
@interface ContainableTag{}
@ContainableTag public class Foo {}
// ... elsewhere...
/**
* Adds obj as a child element.
* @throws IllegalArgumentException if obj is not tagged with
* the ContainableTag annotation.
*/
public void addElement(Object obj){
if (!obj.getClass().isAnnotationPresent(ContainableTag.class))
throw new IllegalArgumentException("obj is not a ContainableTag");
// add the containable tag as an element
}
Entonces considera si realmente no crees que esto se vea mejor:
interface ContainableTag {}
public class Foo implements ContainableTag {}
// ... elsewhere...
public void addElement(ContainableTag ct){
// add the containable tag as an element
}
Claro, la interfaz de etiquetado no proporciona información sobre qué comportamiento proporciona el tipo en sí, pero sí permite que otros tipos impongan esta propiedad de no comportamiento. Sin duda, me habría ahorrado muchos errores molestos si ObjectOutputStream
tuviera un método writeObject (Serializable)
en lugar de writeObject (Object)
.
Editar: Tengo soporte no insignificante aquí.