docenciait / ProgramacionDAW

0 stars 0 forks source link

Interfaz Comparable??? #17

Closed javierbarbe closed 4 years ago

javierbarbe commented 4 years ago

Buenas Ivan Te escribo porque me esta dando quebraderos de cabeza implementar la interfaz Comparable. Concretamente hay un par de ejercicios del Tema 10 del libro de LuisJoseSanchez concretamente los ejercicios 8 y 9. El ejercicio 8 lo he resuelto sin implementar la interfaz comparable ( mas que nada ... porque no entiendo lo que hace en las soluciones propuestas por LuisJose) pero , al llegar al ej9... se hace evidente que saber manejar esa interfaz facilita bastante la vida al programador... Por ello te escribo esta issue para intentar comprender la sobreescritura de los metodos compareTo y equals. Un saludo!!

ivanjimenez commented 4 years ago

Hola, Javier:

Estoy preparando una serie de videos para las Colecciones. JL Sánchez lo utiliza de esa forma, pero la verdad que se suele implementar la interfaz Comparable y Cloneable para comparar y copiar objetos. La parte de Colecciones de ese libro no me termina de gustar porque se salta conceptos importantes. No obstante, porque estoy haciendo material para todos, te dejo un par de recursos para vayas viendo cómo se implementa un interfaz Comparable y otro Cloneable para que vayas viendo cómo se puede implementar estos interfaces y para qué se utilizan. Está claro que el primero es para comparar objetos y el segundo para clonarlos totalmente.

https://www.aprenderaprogramar.com/index.php?option=com_content&view=article&id=587:ejercicio-ejemplo-resuelto-interface-comparable-y-metodo-compareto-api-java-comparar-objetos-cu00913c&catid=58&Itemid=180

http://www.sc.ehu.es/sbweb/fisica/cursoJava/fundamentos/clonico/clonico1.htm

Hay un libro que está muy bien que comenté de D Liang "Introduction to Java Programming and Java Structures" en sus capítulos 11.10, 13.6 y 13.7 pero están en inglés donde también habla de esto de manera más completa. No obstante, si con estos recursos y con los videos que suba no te vale ya me comentas.

ivanjimenez commented 4 years ago

Hola, Javier, no sé si habrás visto la respuesta anterior. Pero para que te quede más claro el uso de los métodos compareTo y equals . En primer lugar, estos dos métodos tienen que implementarse a partir del interfaz Comparable.

Imaginemos que tenemos una clase Gato y queremos crear dos métodos que comparen dos objetos Gato así como otro método que diga si son iguales. Podría hacer muchos métodos que se llamasen de cualquier forma. Pero en java existe un interfaz llamado Comparable que tiene dos métodos a implementar que son compareTo y equals. Estos dos métodos tienen una signatura o cabecera que no se pueden cambiar y ambos. Mientras compareTo devuelve un int el método equals retorna un boolean. Por qué se hace así, pues porque todos los objetos que implementen dicho interfaz tendrán esos dos métodos y no otros con otros nombres.

Sigue más abajo

*/
public class Gato implements Comparable<Gato> {
    private String nombre;
    private String color;
    private String raza;

public Gato(String nombre, String color, String raza) {
    this.nombre = nombre;
    this.color = color;
    this.raza = raza;
}
public String getNombre() {
    return nombre;
}
public String getRaza() {
    return raza;
}
public String toString() {
    return "Nombre: " + this.nombre + "\nColor: " + this.color + "\nRaza: " + this.raza;
}
public int compareTo(Gato g) {
    return (this.nombre).compareTo(g.getNombre());
}
public boolean equals(Gato g) {
    return (this.nombre).equals(g.getNombre());
}
}

¿Cómo se implementa el interfaz Comparable? Pues hay que entender qué son los genéricos y la notación <> diamante donde podremos poner cualquier tipo de objeto que predefinamos (ver video de Genéricos de Programación). En nuestro caso es el objeto Gato. Pues entonces se pone en la cabecera de la clase

public class Gato implements Comparable <Gato> 

Y luego se implementa el método compareTo (entre otros métodos que tenga la clase). En el ejemplo anterior lo que pasa es que llama al método compareTo de los Strings que ya viene implementado. Pero podríamos hacer algo así:

public int compareTo(Gato g) {

   if (this,getNombre().equals(g.getNombre)
       return 0;
   else 
      return 1;

}

Y el método equals de forma análoga pero ya está realizada en el ejemplo porque llama al equals de String.

Si queremos hacer un ArrayList de Gato:

ArrayList g1 = new ArrayList;

Y aquí llamas a los métodos.

Ahora, este es un ejemplo sencillo, los que tú dices el método compareTo y equals tienen un poco más de dificultad y te lo explico en otro post abajo.

ivanjimenez commented 4 years ago

Tomemos los ejemplos de JL Sánchez. Ejercicio 9 de Colecciones:

import java.util.Objects;

public class Carta implements Comparable<Carta>{

  private static String[] n = {"as", "dos", "tres", "cuatro", "cinco", "seis", "siete", "sota", "caballo", "rey"};
  private static String[] p = {"bastos", "copas", "espadas", "oros"};

  private Integer numero;
  private String palo;

  public Carta() {
    this.numero = (int)(Math.random()*10);
    this.palo = p[(int)(Math.random()*4)];
  }

  public int getNumero() {
    return numero;
  }

  public String getPalo() {
    return palo;
  }

  @Override
  public String toString() {
    return n[numero] + " de " + palo;
  }

  @Override
  public boolean equals(Object obj) {
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    final Carta other = (Carta) obj;
    if (!Objects.equals(this.numero, other.numero)) {
      return false;
    }
    if (!Objects.equals(this.palo, other.palo)) {
      return false;
    }
    return true;
  }

  @Override
  public int compareTo(Carta c) {
    if (palo.equals(c.getPalo())) {
      return numero.compareTo(c.getNumero());
    } else {
      return palo.compareTo(c.getPalo());
    }
  }
}

Cómo funciona equals?

 @Override
  public boolean equals(Object obj) {
 // Hay que tener en cuenta que equals se le pasa un Object. Todo hereda de Object, es decir, que // valdría como parámetro obj cualquier tipo de objeto.
    if (obj == null) { //verifico si está vacío, no hay objeto, es un chequeo necesario.
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    final Carta other = (Carta) obj; // Aquí se realiza un "Casting" de objetos, pasando un objeto obj a 
// otro de tipo Carta
// Objects es un objeto estático que tiene algunos métodos útiles como equals en el que comparas 
// dos tipo Integer (recuerda, son los objetos envolutura, mira los videos de Colecciones I)
    if (!Objects.equals(this.numero, other.numero)) {
      return false;
    }
    if (!Objects.equals(this.palo, other.palo)) {
      return false;
    }
// Si en alguno de los casos anteriores es falso, ya no son iguales los objetos
// comparo los palos y los números y si son iguales los anteriores if no devuelven nada y sí
// el siguiente true
    return true;
  }

El compareTo es más sencillo:

@Override
  public int compareTo(Carta c) {
    if (palo.equals(c.getPalo())) {
      return numero.compareTo(c.getNumero());
    } else {
      return palo.compareTo(c.getPalo());
    }
  }

Fíjate que Integer y String tienen un objeto compareTo que utlizamos aquí para comparar el objeto actual con el que tiene como parámetro.

Dime si lo entiendes mejor así. Saludos

javierbarbe commented 4 years ago

Buenas Ivan... despues de leer lo que has mandado me ha quedado un poco mas claro... Ahora bien... he encontrado que Eclipse realiza la sobreescritura del metodo equals de los campos que quieras de manera eficiente y automatica, lo que ahorra el tener que reinventar la rueda cada vez que se quiera comparar un objeto. Un saludo

ivanjimenez commented 4 years ago

Hola, Javier:

Quiero que se os quede lo mejor posible, pregunta y que no se te quede nada sin aclarar. Utilizar asistencia de código para ese método no es que esté mal, pero para el futuro.

Evidentemente, hay que entender qué realiza. No nos sirve saber qué realiza y deberías intentar siempre escribir tu propio código sin utilizar el asistente.

Cierro esta issue.

Saludos