En Java la clase de la que heredan (directa o indirectamente) todas las clases es la clase Object
: todas las clases heredan los métodos de esta Object
. Cada vez que una clase hereda un método de una superclase, se tiene la oportunidad de sobrescribir el funcionamiento del método.
La sobrescritura de métodos heredados se usa para definir el comportamiento específico de un método que tiene un funcionamiento demasiado general en una superclase. Esto se denomina Override
.
Cuando sobrescribimos métodos podemos ayudar al compilador a evaluar si hacemos lo correcto utilizando la etiqueta @Override
en la definición del método. Esto se comenta con más detalle en la sección sobre Herencia de Clases.
La clase Object tiene una serie de métodos, aunque solo sobrescribiremos los métodos que consideremos necesarios:
Método | Descripción |
---|---|
String toString() | Devuelve la representacion en String del objeto |
boolean equals(Object obj) | Indica si el objeto actual es igual al parametro obj |
Object clone() | Devuelve una copia del objeto. El objeto debe implementar la interface Cloneable |
int hashCode | Devuelve el código hash del objeto. Está enfocado en el uso de tablas Hash como las provistas por HashMap |
void finalize() | Método llamado por el recolector de basura, cuando no quedan referencias a ese objeto |
Class getClass() | Devuelve la clase del objeto |
void notify() | Despierta un hilo de ejecución que está en estado de espera |
void notifyAll() | Despierta todos los hilos que están en espera |
void wait() | Pone en espera un hilo de ejecución, hasta que se llame a notify() o notifyAll() |
void wait(long time) | Pone en espera la cantidad de tiempo, o hasta notify() o notifyAll() |
void wait(long time, int nanos) | Pone en espera al hilo de ejecución |
Dependiendo de la finalidad de nuestra clase nos podría interesar sobrescribir unos métodos u otros.
Todo método declarado como final
en una clase, no puede ser sobrescrito. Esto ocurre también en la clase Object. Los únicos métodos que se pueden sobrescribir son: toString(), equals(), hashCode(), clone() y finalize().
Los IDEs ofrecen la posibilidad de generar de forma automática algunos métodos de la clase Object.
Desde la pestaña Source
del menu, o haciendo clic derecho en el editor de texto → Source
accedemos al siguiente menu:
Pulsando sobre la generación de esos métodos, eclipse nos ayuda a generarlos.
Por ejemplo, la implementación del método toString()
devuelve un String utilizando el valor de todos los atributos. Podemos modificarlo si queremos mostrar menos, o dar otro formato.
Tal como se indica en la documentación de la clase Object, el método toString()
se usa para obtener una “representacion textual” de un objeto.
El método toString() está enfocado en la representación de un objeto hacia el usuario. La información que muestra debe ser concisa pero explicativa para que lo entienda una persona.
El método de la clase Object
devuelve un String compuesto por el nombre de la clase, una @, y el código hash
en hexadecimal de ese objeto.
Cuando nosotros creamos una clase, puede que necesitemos tener un modo textual de representar a los distintos objetos. Por lo que se recomienda que todas las subclases de Object lo sobrescriban.
Es el programador que crea la clase quien debe elegir qué información considera oportuna para representar al objeto.
public class Persona{ private String dni; private String nombre; private String apellido1; private String apellido2; private LocalDate fechaNacimiento; private float altura; private float peso; private String colorOjos; private String complexion; @Override public String toString(){ return dni + " - " + nombre + " " + apellido1 + " " + apellido2; } }
La principal ventaja de sobrescribir toString() es poder mostrar por consola directamente una variable de referencia de una clase. Automáticamente se llamará al método toString() de esa clase.
Persona persona1 = new Persona(); System.out.println(persona1); // Se ejecuta implicitamente el método toString()
El método equals se usa para saber si un objeto es igual a otro, devolviendo true
o false
.
Cuando dos objetos pertenecen a distinta clase, es fácil evaluarlo (nunca serán iguales). Pero cuando dos objetos pertenecen a la misma clase, aunque sean objetos distintos, nos podría interesar establecer un criterio para indicar cuando son iguales.
Por ejemplo:
equals()
devuelve true
si contienen la misma cadena de texto.equals()
devuelve true
cuando representan la misma fecha.
El método equals()
de la clase Object
indica true
únicamente cuando se trata del mismo objeto creado (ambas variables contienen la dirección del mismo objeto), como se explica en el siguiente ejemplo:
Persona persona1 = new Persona(); Persona persona2; //Las dos variables de referencia contienen la misma dirección de memoria //Es decir, apuntan o referencian al mismo objeto persona2 = persona1; //Entonces el método equals heredado de Object persona1.equals(persona2); //Devuelve true //Pero si contienen referencias a objetos distintos persona2 = new Persona(); persona1.equals(persona2); //Devuelve false
Aunque establecer un criterio para comparar 2 objetos es bastante sencillo (por ejemplo 2 personas son iguales si tienen el mismo dni), se deben cumplir unas normas.
Se definen unas normas que toda implementación del método equals() que se precie, debe cumplir.
x
distinto de null, x.equals(x) devuelve true
.x
e y
distintos de null
, x.equals(y) == y.equals(x).x
, y
y z
distintos de null
, si x.equals(y) es true, y y.equals(z) es true, entonces x.equals(z) debe ser true. x
e y
distintos de null
, todas las llamadas a x.equal(y) devuelven siempre el mismo valor, mientras no cambien el valor de los atributos comparados.null
, x.equals(null) debe ser false
.Atendiendo a esto podemos seguir el siguiente patrón a la hora de sobrescribir este método:
public class Persona{ private String dni; private String nombre; private int edad; @Override public boolean equals(Object obj){ if (this == obj){ //Si referencian al mismo objeto return true; } if (obj == null){ //Si lo que recibe es null return false; } if (this.getClass() != obj.getClass()){ //Si no son de la misma clase return false; } Persona other = (Persona) obj; //Si sus valores no son iguales if ( ! ((this.dni.equals(other.dni) && (this.nombre.equals(other.nombre)) && (this.edad == other.edad))){ return false; } return true; //Si no he devuelto false, es que son iguales } }
Si puede que nuestros objetos se almacenen el algún tipo de estructura Hash debemos sobrescribir el método hashCode()
en concordancia con el método equals()
.
© 2024 Fernando Valdeón