2008-10-07 15 views
8

Si tengo una clase que necesita implementar una interfaz pero uno o más de los métodos en esa interfaz no tienen sentido en el contexto de esta clase en particular, ¿qué debería hacer? ¿Hago?Comportamiento correcto para métodos de interfaz que no se pueden implementar

Por ejemplo, digamos que estoy implementando un patrón de adaptador donde quiero crear una clase contenedora que implemente java.util.Map envolviendo algún objeto inmutable y exponiendo sus datos como pares clave/valor. En este caso, los métodos put y putAll no tienen sentido ya que no tengo forma de modificar el objeto subyacente. Entonces, la pregunta es: ¿qué deberían hacer esos métodos?

Respuesta

17

Cualquier método que no se puede implementar de acuerdo con la semántica de la interfaz debe arrojar un UnsupportedOperationException.

+0

UnsupportedOperationException suele ser el camino a seguir, a menos que sepa que el método se llamará de todos modos, y desea hacer más de un "no-op", en cuyo caso devolver nulo o similar es lo mejor que puede hacer . – skaffman

+0

... parece que respondiste tu propia pregunta, Mike ... – Sandman

+0

El hecho de que necesites hacer esto podría considerarse un problema de diseño. – Aidos

10

Eso depende de su caso de negocio. 2 opciones:

Use el que tenga más sentido. Si no hace nada, no está obedeciendo el contrato de la interfaz. Sin embargo, lanzar una excepción de tiempo de ejecución puede causar estragos en el código de llamada. Por lo tanto, la decisión tendrá que tomarse en función de cómo va a utilizar la clase. Otra opción sería usar una interfaz más simple o diferente, si es posible.

Tenga en cuenta que la biblioteca de Java va por la ruta de excepción en el caso específico de las colecciones read-only.


Se señaló a continuación que UnsupportedOperationException es una parte del marco de las colecciones java. Si su situación está fuera de las colecciones, y la semántica le molesta, puede pasar su propia NotImplementedException, o si ya está utilizando commons-lang, puede usar theirs.

3

Sus dos opciones son realmente sólo:

  1. hacer nada.
  2. Lance una excepción.

Ambos tienen desventajas. En el primer caso, al tener un método vacío, puede engañar al programador para que piense que algo sucedió con sus datos. El segundo caso rompe la idea de polimorfismo inherente a las interfaces.

2

Tenga en cuenta que UnsupportedOperationException solo está bien debido a la propiedad particular de Java Collections Framework, que las implementaciones pueden "ejecutar" la implementación de parte de la interfaz porque son inmutables.

Así que está bien para put() (suponiendo que todos los métodos de mutador hagan lo mismo), pero un mapa que arroje UnsupportedOperationException del método size() simplemente se romperá. Si intenta implementar un tipo de mapa que no sabe qué tan grande es, puede tener problemas (aunque a veces puede devolver Integer.MAX_VALUE).

También tenga en cuenta que la documentación de la clase para UnsupportedOperationException dice que es parte de Java Collections Framework. Fuera del marco de colecciones, no se espera arrojar UnsupportedOperationException y podría dar lugar a un código de cliente que simplemente no funciona. Claro, es una RuntimeException, pero solo porque puedes lanzarla no significa que tu método funcionará si siempre lo hace.

En lugar de eso, podría refactorizar la interfaz (tal vez dividiéndola en dos), o bien repensar por qué esta clase afirma ser un Foo cuando simplemente no lo es, ya que no puede hacer las cosas que los Foos están definidos Poder hacer.

5

Esa colección de solo lectura ya provista por Java arroja la excepción UnsupportedOperationException durante las operaciones de escritura que ya es un hack de diseño desafortunado. Las clases de colección deberían haber sido escritas con interfaces separadas de solo lectura y de solo escritura que son heredadas por la interfaz completa de lectura-escritura. Entonces sabes lo que estás obteniendo.

+0

aún se encontraría con un problema en el que las API requerirían la interfaz de lectura/escritura, incluso en circunstancias en las que solo sería de lectura. Pero estoy de acuerdo, la flexibilidad sería agradable. –

+0

Esta API de colecciones habría terminado en un lío ilegible, si se hubiera tomado esta decisión de diseño. –

+0

El problema en el caso específico de Java no proviene de las interfaces, sino de AbstractCollection, etc. No se puede heredar de AbstractROCollection y AbstractRWCollection, por lo que la jerarquía de clases se dividiría en dos en la parte superior. Vector y ReadOnlyVector estarían muy relacionados. –

Cuestiones relacionadas