Unidad Didáctica 4 Diseño de tipos Igualdad, representación, código, copia y relación de orden Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos Versión 1.0.1 Índice Diseño de Tipos Igualdad, representación y código hash Clonación Orden natural UD4: Diseño de tipos Diseño de tipos - Guía Elección de propiedades: Simples: sus valores no dependen de otras Derivadas: dependen del resto de propiedades Elección del conjunto de métodos del tipo Establecer criterios para las siguientes propiedades: Criterio de igualdad Representación como cadena Código como entero (Código Hash) Orden natural Clonación o copia UD4: Diseño de tipos Tipos El tipo Object Interfaz Cloneable Interfaz Copiable Interfaz Comparable UD4: Diseño de tipos El tipo Object La clase Object es la raíz de la jerarquía de clases en Java y obligatoria de ser extendida por cualquier nueva clase. Algunos de sus métodos públicos son: ... boolean equals(Object o); int hashCode(); String toString(); ... equals: se utiliza para comparar si dos objetos son iguales. hashCode: devuelve el código hash del objeto. Dos objetos iguales tendrán el mismo código hash. toString: devuelve una cadena de texto que representa al objeto. UD4: Diseño de tipos Tipos – El tipo Object equals: equals/toString: Simetría: si un objeto es igual a otro, el segundo también es igual al primero. Transitividad: si un objeto es igual a otro, y este segundo es igual a un tercero, el primero también será igual al tercero. Si dos objetos son iguales, sus representaciones en forma de cadena también lo serán. equals/hashCode: Si dos objetos son iguales, sus códigos hash tienen que coincidir. UD4: Diseño de tipos Tipos – Copia package java.lang; public interface Cloneable { } Esta interfaz no añade métodos pero habilita que los objetos puedan invocar el método clone de Object. Si una clase no la implementa se lanzará la excepción CloneNotSupportedException cuando se solicite dicho método. UD4: Diseño de tipos Tipos – Copia public interface Copiable<T> extends Cloneable { T clone(); } Esta interfaz, de diseño propio, es paramétrica y hace referencia a un tipo genérico T que será instanciado en cada caso. Permite que los objetos puedan invocar el método clone de Object desde el código de cualquier clase de Java devolviendo un objeto del tipo T. Propiedad clone/equals: Si un objeto se obtiene a partir de otro haciendo uso del método clone, ambos objetos serán iguales pero no idénticos. UD4: Diseño de tipos Tipos – Copia: Copia superficial o clonación por defecto clone: si el objeto tiene atributos de tipo objeto se realiza una copia de sus referencias, no se crean nuevos objetos. Ejemplo: clonación superficial de objetos de tipo Circulo Objeto clonado Objeto original (Circulo) referencia 5 (Circulo) centro radio (Punto) 0 0 UD4: Diseño de tipos x y referencia 5 centro radio Tipos – Copia: Copia en profundidad copia: si el objeto tiene atributos de tipo objeto se realiza una copia de dichos atributos en nuevos objetos. Es necesario generar el código en cada caso. Ejemplo: copia en profundidad de objetos de tipo Circulo Objeto original Objeto copiado (Circulo) referencia 5 (Circulo) centro radio (Punto) 0 0 UD4: Diseño de tipos referencia 5 centro radio (Punto) x y 0 0 x y Tipos – El tipo Comparable package java.lang; public interface Comparable<T>{ int compareTo(T o); } compareTo establece un orden natural para los objetos. Debe coincidir en criterio con el método equals. Valor entero devuelto: Negativo si this es menor que o, es decir, está antes en el orden. Cero si this es igual a o, es decir, el método equals devuelve true entre ellos. Positivo si this es mayor que o, es decir, está después en el orden. UD4: Diseño de tipos Tipos – El tipo Comparable. Propiedades compareTo: Simetría: si el resultado de comparar un objeto con otro es cero, el resultado coincide a la inversa. Transitividad: si el signo de comparar un objeto con otro coincide con el signo de comparar el segundo con un tercero, entonces también coincide con el signo de comparar el primero con el tercero. equals/compareTo: Si dos objetos son iguales, el resultado de su comparación será igual a cero, y viceversa. UD4: Diseño de tipos Diseño de tipos Copiable<Punto> Comparable<Punto> extends interface Punto A la hora de diseñar un nuevo tipo de datos debemos decidir qué tipo de copia permite y qué orden natural e igualdad tendrán los objetos de dicho tipo. Supongamos que los puntos sean iguales cuando coincidan sus dos coordenadas, sean copiables en forma superficial y su orden sea de menor a mayor por su coordenada X y a igualdad de ésta por su coordenada Y. UD4: Diseño de tipos Aplicación: el tipo Punto Interface Punto public interface Punto extends Copiable<Punto>, Comparable<Punto>{ Double getXl(); Double getYl(); void setX(Double x); void setY(Double y); } UD4: Diseño de tipos Aplicación: el tipo Punto PuntoImpl: equals public class PuntoImpl implements Punto{ ... public boolean equals (Object o){ boolean res = false; if(o instanceof Punto){ Punto p = (Punto) o; res = getX().equals(p.getX()) && getY().equals(p.getY()); } return res; } ... UD4: Diseño de tipos Aplicación: el tipo Punto PuntoImpl: toString y hashCode ... public String toString(){ String s; s=“(“ + getX()+”,"+getY() + “)”; return s; } public int hashCode(){ return getX(). hashCode() * 31 + getY().hashCode(); } } UD4: Diseño de tipos Aplicación: el tipo Punto Ejemplo de uso ... Punto p1 = new PuntoImpl(6.0,4.0); Punto p2 = new PuntoImpl(6.0,4.0); if(p1.equals(p2) && p1!=p2){ mostrar(p1 + " y " + p2 + " son iguales pero no idénticos"); } ... UD4: Diseño de tipos Aplicación: el tipo Punto public class PuntoImpl implements Punto { ... public Punto clone(){ Punto copia=null; try{ copia=(Punto)super.clone(); } catch(CloneNotSupportedException e){e.printStackTrace();} return copia; } } ... Punto p1 = new PuntoImpl(2,8); Punto p2 = p1.clone(); mostrar(p1 + " " + p2); p2.setX(7); mostrar(p1 + " " + p2); ... UD4: Diseño de tipos Aplicación: el tipo Punto public class PuntoImpl implements Punto { ... public int compareTo(Punto p){ int cmp = getX().compareTo(p.getX()); if(cmp == 0){ cmp = getY().compareTo(p.getY()); } return cmp; } … } ... Punto p1 = new PuntoImpl(6,4); Punto p2 = new PuntoImpl(6,4); if(p1.compareTo(p2)==0){ mostrar(p1 + " y " + p2 + " son iguales"); }else{ if(p1.compareTo(p2) < 0){ mostrar(p1 + " está antes en el orden que " + p2); }else{ mostrar(p1 + " está después en el orden que " + p2); } UD4: Diseño de tipos