2010-06-10 17 views
9

tengo una interfaz y quiero que todos los que implementa esta interfaz para implementa un overrridden "es igual a" método.cumplir "iguales" en una interfaz

¿Hay alguna manera de asegurarse de que eso suceda?

La manera que supongo que esto va a pasar es que la clase que implementa la interfaz de mi obtendrá automáticamente los iguales de objetos, por tanto, hacer feliz a la interfaz.

+1

¿Cuál es su razón de ser para esto? –

+0

El caso específico que encontré cuando surgió esta pregunta; Tengo una interfaz que implementó varias clases. Estas clases están identificadas por un identificador único. Entonces, si dos identificadores son iguales, los objetos deben considerarse iguales. En un momento tuve una lista de una de esas clases y quería saber si un objeto nuevo ya existía en la lista. Pensé que sería elegante usar List.contains (..) para este control. Pero eso requeriría que pudiera estar seguro de que los iguales fueron anulados. Sin embargo, es fácil de resolver de otras maneras. Una clase abstracta también habría funcionado bien. – Fredrik

Respuesta

10

No, sólo se puede crear una clase abstracta en lugar de una interfaz de esta manera:

public abstract class MyApi { 

    public final boolean equals(Object other) { 
    if (other == this) { 
     return true; 
    } 
    if (other instanceof MyApi) { 
     return equals((MyApi)other); 
    } 
    return false; 
    } 

    protected abstract boolean equals(MyApi other); 

} 

o una versión más sencilla:

public abstract class MyApi { 

    public boolean equals(Object other) { 
    throw new UnsupportedOperationException("equals() not overridden: " + getClass()); 
    } 

} 

EDITAR (que probarlo después de la comentario de @CodeConfident, gracias! Nunca asumí que funcionaría):

También puede simplemente declarar equals() en un ab clase stract (! no en una interfaz) y, por tanto ocultar la aplicación Object y hacer cumplir una nueva aplicación en cualquier subclase:

public abstract class MyApi { 

    public abstract boolean equals(Object obj); 

    public abstract int hashCode(); 

} 

De todos modos siempre se debe aplicar equals() y hashCode() juntos para cumplir el contrato.

+0

Si defiende el uso de una clase abstracta, ¿por qué no declarar que los iguales (Objeto) son abstractos? – ILMTitan

+2

@ilmtitan: ¡no puede declarar un resumen de método heredado! –

+0

@ArneBurmeister - Esto no es verdad (al menos ahora). Absolutamente puede anular un método heredado con un método abstracto dentro de una clase abstracta. Vea esta respuesta: https://stackoverflow.com/questions/1718112/tostring-equals-and-hashcode-in-an-interface#answer-1718170 – AjahnCharles

3

No. Usted puede agregarlo a la interfaz (y por lo tanto los javadocs), pero si Object.equals tiene la misma firma, no se puede tener el compilador hacen anularlo.

1

Editar: Probablemente no es una buena idea (ver comentario de Farmboy). Saliendo de aquí para la posteridad.

En lugar de utilizar equals(Object obj) de la clase Object, haga que lo compare con una implementación de su interfaz.

public interface MyInterface { 
    public boolean equals(MyInterface mi); 
} 

Por lo tanto,

public class MyImplementation implements MyInterface { 
    public boolean equals(MyInterface mi) 
    { 
    if(this == mi) 
     return true; 
    // for example, let's say that each implementation 
    // is like a snowflake...(or something) 
    return false; 
    } 
} 

Y luego:

public class Main { 

    public static void main(String[] args) 
    { 
    Object o = new MyImplementation(); 
    MyImplementation mi1 = new MyImplementation(); 
    MyImplementation mi2 = new MyImplementation(); 

    // uses Object.equals(Object) 
    o.equals(mi1); 
    // uses MyImplementation.equals(MyInterface) 
    mi1.equals(mi2); 
    // uses Object.equals(Object) 
    mi2.equals(o); 
    } 
} 
+2

Esto no es una buena idea. Todo lo que llame igual (como poner un objeto en un 'Conjunto' no lo llamará igual, sino el 'real'. Entonces obligaría a la clase implementadora a implementar este método, y cualquier buen programador implementaría el 'real' también. –

+0

Buen punto - No había pensado en eso. Quisiera más detalles del solicitante en cuanto a la motivación detrás de esta pregunta. – Catchwa

0

supongo que no puede haber dos razones por las que tal un método equals podría ser necesario

  1. Quiere para asegurar que todas las clases en su aplicación (o un subconjunto de ellas) "tendrá" el método igual. Algo así como la aplicación de estándares, o asegurarse de que algunas de las API que utiliza funcionen como deberían (y esperan que los iguales se implementen correctamente. Digamos que usa Maps bastante y quiere estar absolutamente seguro de que un subconjunto de clases es definitivamente posible teclas) Si ese es el caso, este no es el camino a seguir. En este caso, no podrá hacerlo, pero incluso si lo está, no sería correcto. Debes buscar herramientas de cobertura de códigos y mejores pruebas de unidades.

  2. usted no desea que el método es igual, pero quieren un método similar. En este caso, puede crear otro método con un nombre similar en la interfaz.

3

No. Una interfaz es un contrato que garantiza que los métodos existe.

No hay ningún mecanismo para hacer cumplir que los métodos se deben anular en una interfaz.

0

He experimentado escribiendo el contrato requerido para equals en JavaDoc. Pero el requisito de que hashCode sea consistente con equals resulta en un contrato muy complejo para hashCode. Así que me di por vencido y creé una clase base abstracta con una implementación final de los dos métodos.

Cuestiones relacionadas