Herramientas de usuario

Herramientas del sitio


bloque3:overrideobject

Sobrescritura de métodos de la clase Object

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.

Etiqueta @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.

Métodos de la clase Object

La clase Object tiene una serie de métodos, aunque solo sobrescribiremos los métodos que consideremos necesarios:

MétodoDescripció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 hashCodeDevuelve 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.

Impedir la sobrescritura

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().

Generar métodos desde Eclipse

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.


Override: método toString()

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()

Override: método equals()

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:

  • Con dos objetos String distintos, el método equals() devuelve true si contienen la misma cadena de texto.
  • Con dos objetos LocalDate distintos, el método 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.

Normas para sobrescribir equals()

Se definen unas normas que toda implementación del método equals() que se precie, debe cumplir.

  • Debe ser reflexivo; para x distinto de null, x.equals(x) devuelve true.
  • Debe ser simétrico; para x e y distintos de null, x.equals(y) == y.equals(x).
  • Debe ser transitivo; para 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.
  • Debe ser consistente; para 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.
  • Si x es distinto de 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

bloque3/overrideobject.txt · Última modificación: 16/09/2024 20:53 por 127.0.0.1