Object y Final
La clase Object
Java define una clase especial o clase suprema denominada Object, que es la superclase de cualquier otra clase que se pueda crear en tu proyecto. Implica que cualquier clase creada heredará una serie de métodos que algunos nos interesa sobreescribir. Otra implicación es que una variable de tipo Object podría referenciar a un objeto de cualquier clase.
Algunos métodos definidos por Object y que heredará cualquier clase son:
Todos pueden ser sobreescritos excepto getClass() que es final (lo vemos a continuación).
Método HashCode
Devuelve un identificador o “dni” de cada objeto único. Se puede sobreescribir pero no es recomendable.
Métodos Equals
Se utiliza la sobreescritura para comparar contenido interno de los objetos. Recordad que con el operador == se comparan referencias a objetos.
Ejemplo del uso de ambos métodos:
public class Student {
private int id;
private String name;
public Student(int id, String name) {
this.name = name;
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class HashcodeEquals {
public static void main(String[] args) {
Student alex1 = new Student(1, "Alex");
Student alex2 = new Student(1, "Alex");
System.out.println("alex1 hashcode = " + alex1.hashCode());
System.out.println("alex2 hashcode = " + alex2.hashCode());
System.out.println("Checking equality between alex1 and alex2 = " + alex1.equals(alex2));
}
}
Tienen diferente código o id porque porque son dos instancias diferentes de la clase, aunque el contenido de ambos objetos es el mismo. Es decir equals sin sobreescribir usa el hashCode(). Por tanto es necesario sobreescribir el equals:
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (!(obj instanceof Student))
return false;
if (obj == this)
return true;
return this.getId() == ((Student) obj).getId();
}
El operador instanceof lo trabajaremos más adelante, un enlace de referencia. Tanto hashCode() como equals() se usaran mucho con colecciones de objetos.
Ejemplo de sobreescritura con equals()
class Punto2D{
private int x;
private int y;
private String nombre;
public Punto2D(int x, int y, String nombre) {
super();
this.x = x;
this.y = y;
this.nombre=nombre;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Punto2D)) return false;
Punto2D punto = (Punto2D) o;
return (x == punto.x) && (y == punto.y);
}
}
El modificador final
El modificador final lo hemos usado para crear constantes de una clase, es decir una vez creada e inicializada no se puede modificar:
private final float PI = 3.1416f;
Pero ahora habiendo usado herencia lo podemos usar con métodos que no queramos que se sobreescriba. Es decir desde la clase padre podemos indicar con final, que métodos no queremos que se modifiquen en los hijos o subclases. Es una manera de “protección” funcional en herencia. Para declarar un método final seguimos esta sintaxis: modificador_acceso final tipo nombreMetodo(listaParam)
Ejercicio 1
En un ejemplo de herencia prueba el modificador final, y provoca el error de intentar sobreescribir un método del padre.
Final con Clases
Este modificador también lo podemos usar con clases, dichas clases no podrán ser heredadas. También implica que sus métodos serán final y no podrá ser declarada abstracta (abstract), aspecto que veremos a continuación.
Ejercicio 2
Hacer una clase llamada Deposito que tiene un nombre, un largo, un ancho y un alto. Hacer un método equals que devolverá true cuando dos depósitos tengan el mismo volumen (largo * ancho * alto).