2012-04-20 20 views
7

Si implemento equals() y hashCode() en las clases primaria y secundaria, ¿es necesario llamar al super.equals() en equals() en la clase secundaria, p.¿Llamar a super.equals y super.hashCode en la clase infantil?

public boolean equals(Object obj) { 

    if (obj.getClass() != ChildClass.class) { 
    return false; 
    } 

    return super.equals() && this.var == ((ChildClass) obj).var; 

} 
+0

P.S. Supongo que la clase principal no es Object y está dando la definición correcta de 'equals' y' hashCode'. –

Respuesta

8

No, eso no es necesario, y probablemente sería incorrecto. De hecho, parte de la razón por la que está anulando equal es porque super.equals no da el comportamiento correcto (¿no?).

O dicho de otra manera, si super.equals da el comportamiento correcto, es probable que no necesita ir a la dificultad de anular la misma.

Pero si está anulando equals, entonces sí, necesita anular hashCode, también.

+2

'SuperClass.equals' obviamente solo puede comparar instancias' SuperClass' y no sabe nada sobre 'SubClass'. Es por eso que 'SubClass' debe anularlo, incluso si es perfectamente correcto en términos de' SuperClass'. Pero sería absurdo volver a implementar su comportamiento en 'SubClass' (o en cada una de muchas subclases) en lugar de llamar' super.equals' (antes de comparar las partes de la subclase), ¿verdad? –

+4

Bueno, si se está aplicando la igualdad de valor, puede ser necesario llamar 'super.equals()' para tener campos heredados revisados ​​por la igualdad ... – Alan

+0

realidad, muchas veces sólo se necesita añadir cheques para los campos adicionales (como @ Alan mencionó), por lo que es necesario llamar a 'super.equals()'. Además, si solo está agregando campos, no necesita _ para anular 'hashCode()'. Si – jtahlborn

2

Si su super clase no implementa iguales, a continuación, llamar super.equals le conseguirán la implementación de objetos que sólo se compara referencias, por lo que en cualquier aplicación normal, es igual a la que desea comparar una clave de negocio se haría realidad causa muchos falsos negativos

Dicho esto, su implementación anterior realmente no es diferente semánticamente que la implementación predeterminada de igual en Objeto ya que solo está usando == para la comparación.

En cuanto a hashCode, si reemplaza a igual, realmente debe anular hashCode para mantener el contrato de los dos. Por ejemplo, si está utilizando una clave comercial para iguales, probablemente debería usar la misma clave comercial para el código hash, de modo que dos objetos que son iguales generen el mismo código hash.

0

EDITAR

te acabo di cuenta utiliza la igualdad de clases, no instanceof - lo que significa que la reflexividad habría ser correcta. En su ejemplo, el uso de super.equals es probablemente correcto, siempre que la superclase no proporcione una definición de igualdad que sea contraria a la que desea su subclase (como Object, por ejemplo).

El punto principal es que la definición de igualdad debe provenir de exactamente un tipo (clase o interfaz) en la jerarquía de su clase. Si la implementación de esa definición se aprovecha de super.equals, está bien.

FIN EDITAR, texto original a continuación

Es casi seguro que lo peor que puede hacer, porque violaría la propiedad reflexiva de la igualdad.

Digamos que tiene una Forma, y ​​es igual a otra Forma si son del mismo tipo: Cuadrado es igual a Cuadrado, Círculo es igual a Círculo, etc. Ahora extiende eso para hacer una Plaza de Color que agrega una verificación de color.

Shape shape1 = new Shape(SQUARE); 
Shape shape2 = new ColoredShape(SQUARE, RED); 

se implementa como ColoredSquare.equalssuper.equals(other) && other.color == this.color, como en su pregunta. Pero ahora, tenga en cuenta que shape1.equals(shape2) == true (desde shape1 solo usa Shape.equals), pero shape2.equals(shape1) == false (ya que agrega la verificación de color).

La moraleja de la historia es que el uso de esta clase de igualdad en cascada es muy difícil, si no imposible. Básicamente, la igualdad debe provenir de exactamente un tipo dentro de la jerarquía de tipo - ya sea Object, su tipo en sí, un tipo estupendo, o alguna de las interfaces que define un contrato (por ejemplo, en el marco de las colecciones, que definen la igualdad para Set, List, etc.)

+0

La moraleja de la historia es más bien que solo debes heredar de las clases abstractas, no de las concretas. Es una violación de esta regla lo que causa los problemas que describes muy bien, no llamar a 'super.equals' del método de subclass' equals'. –

+0

@ PéterTörök No estoy seguro de cómo se aplica, ya que una clase abstracta todavía podría proporcionar 'igual' y' código hash'. En mi ejemplo, pretender 'Shape' es abstracto y tiene dos subclases,' ColoredShape' y 'ColorlessShape', solo el último de los cuales agrega la verificación de color a la igualdad. El mismo problema. – yshavit

+0

No, porque si 'Shape' es abstracto, no puede tener objetos' Shape', solo 'ColoredShape's y/o' ColorlessShape's. Y para estos puedes implementar 'equals' correctamente con o sin reutilizar' super.equals'. Porque nunca se puede tener una situación en la que objectOfA * es un * B * objectOfB pero no es un * A. –

Cuestiones relacionadas