Hoy vamos a anular el método equals() en la clase Point. Antes de ello, he aquí la definición del método equals en la superclase Object.
public boolean equals(Object obj)
Como puedes ver toma un argumento de tipo Object, este válida si el valor actual del objeto y el objeto (obj) pasado como argumento son iguales. Si son iguales retorna verdadero, de lo contrario retorna falso. Ahora vamos a modificar y a hacer un override sobre el método equals de nuestra clase Point, donde equals devolverá true solo si los valores actuales de x y y son iguales al del valor pasado como argumento.
public class Point {
private int xPos,yPos;
public Point(int x, int y) {
xPos = x;
yPos = y;
}
public boolean equals(Point other) {
if (other == null) return false;
if ((xPos == other.xPos) && (yPos == other.yPos)) return true;
else return false;
}
public static void main(String[] args) {
Point p1 = new Point(10, 20);
Point p2 = new Point(50, 100);
Point p3 = new Point(10, 20);
System.out.println("p1 equals p2 is " + p1.equals(p2));
System.out.println("p1 equals p3 is " + p1.equals(p3));
}
}
Si ejecutamos el código anterior imprimirá:
p1 equals p2 is false
p1 equals p3 is true
La salida es como esperábamos, entonces ¿la implementación de equals() fue correcta? Pues Nooooo!!!. Pero ¿por que?, hagamos una modificación al método main antes de explicarlo.
public static void main(String[] args) {
Object p1 = new Point(10, 20);
Object p2 = new Point(50, 100);
Object p3 = new Point(10, 20);
System.out.println("p1 equals p2 is " + p1.equals(p2));
System.out.println("p1 equals p3 is " + p1.equals(p3));
}
Volvamos a ejecutar el programa y obtendremos la siguiente salida.
p1 equals p2 is false
p1 equals p3 is false
Como puedes ver la implementación de equals no ha cambiado pero ahora el resultado no es lo esperado. En este nuevo main usamos Object para declarar p1,p2 y p3. El tipo dinámico de esas tres variables es Point, por lo tanto debe llamar al método equals al que hicimos override, sin embargo la implementación de dicho método es incorrecta. La implementación actual de equals en la clase Point es ignorado y en su lugar llama al método original por defecto de la superclase Object.
Con la intención de superar los sutiles problemas de la sobrecarga (Overloading), puedes usar la anotación @Override, la cual explícitamente le expresa al compilador que tu intención es hacer un override al método. En caso de que el compilador no sea satisfecho con los requisitos necesarios para hacer un override, te devolverá un error, lo cual es una buena señal que te indica que algo hiciste mal. Vamos a intentarlo usando la anotación.
@Override
public boolean equals(Point other) {
if (other == null) return false;
if ((xPos == other.xPos) && (yPos == other.yPos)) return true;
else return false;
}
Ahora si intentamos ejecutarlo lanzará el siguiente error.
Point.java:11: error: method does not override or implement a method from a supertype
@Override
^
1 error
Esto es debido a que la superclase Object no recibe Point en su método equals debemos pasar Object como parámetro.
public class Point {
private int xPos,yPos;
public Point(int x, int y) {
xPos = x;
yPos = y;
}
@Override
public boolean equals(Object other) {
if (other == null) return false;
if (other instanceof Point) {
Point anotherPoint = (Point) other;
if ((xPos == anotherPoint.xPos) && (yPos == anotherPoint.yPos)) return true;
}
return false;
}
public static void main(String[] args) {
Object p1 = new Point(10, 20);
Object p2 = new Point(50, 100);
Object p3 = new Point(10, 20);
System.out.println("p1 equals p2 is " + p1.equals(p2));
System.out.println("p1 equals p3 is " + p1.equals(p3));
}
}
Ya que hemos arreglado ese error y tenemos una correcta implementación de equals, obtenemos el resultado que esperamos.
p1 equals p2 is false
p1 equals p3 is true
Por último recuerda que tu defines las condiciones bajo las cuales equals retorna true.