Autor Tema: Por qué interface Cloneable no obliga a sobreescribir clone API Java (CU00910C)  (Leído 3883 veces)

RaGa

  • Moderador Global
  • Intermedio
  • *******
  • APR2.COM
  • Mensajes: 234
    • Ver Perfil
Hola!

Me ha quedado una duda al leer la lección (CU00910C) donde se desarrolla un ejemplo resuelto implementando la interface Cloneable, perteneciente al package lang del API Java.

Supongamos que al ejemplo lo reescribo de la siguiente manera:

Código: [Seleccionar]
Por ejemplo, si al código del ejercicio resuelto, lo reescribiéramos de la forma:

/* Ejemplo Clase e Interfaz Cloneable aprenderaprogramar.com */

 public class Persona implements Cloneable{

   public int dni, edad;

      public Persona( int d, int e) {     this.dni = d;       this.edad = e;     }

 }

no tendríamos errores de compilación, ¿ por qué ? porque la interface Clonable no declara ningún método abstracto, por lo tanto no me obliga a implementar ninguno en mi clase concreta. ¿Pero y entonces de dónde sale el método clone() ? El método clone() es un método heredado de la clase Object. Pero al no estar declarado en la Interface clonable() no estoy obligado a implementarlo.

Lo que no entiendo es: si el API de java, define una interface clonable() para que la utilicemos para clonar, ¿por qué no entonces declarar la clase abstracta clone()? ¿por qué no exigir al que implemente la interface que es obligatoria su implementación?
« Última modificación: 13 de Mayo 2015, 11:08 por Alex Rodríguez »

Alex Rodríguez

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2050
    • Ver Perfil
Hola Raga, has planteado una pregunta bastante interesante, porque es un caso un tanto extraño.

Para responder la pregunta tenemos la información del api de Java sobre esta interface https://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html:

Citar
public interface Cloneable

A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.

Invoking Object's clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException being thrown.

By convention, classes that implement this interface should override Object.clone (which is protected) with a public method. See Object.clone() for details on overriding this method.

Note that this interface does not contain the clone method. Therefore, it is not possible to clone an object merely by virtue of the fact that it implements this interface. Even if the clone method is invoked reflectively, there is no guarantee that it will succeed.


Nos dice estas cosas:

- Implementar la interface cloneable sirve para indicar que invocar el método clone() (heredado de Object) es legal para realizar copias de objetos de esa clase.

- Si se invoca el método clone sobre un objeto que es de una clase que no implementa la interface Cloneable se obtendrá un error CloneNotSupportedException

- Por convención, una clase que implemente esta interface debe sobreescribir el método clone de object (que es un método protected en object) con un método clone con modificador de acceso public.

Y aquí viene lo que sorprende:

- Tener en cuenta que esta inteface no contiene el método clone. Por tanto, no va a ser posible hacer una copia de un objeto simplemente por el hecho de que una clase implemente esta interface. A no ser que el método clone esté sobreescrito correctamente en la clase, la llamada a clone puede provocar resultados indeterminados.


Y como conclusiones podríamos sacar estas:

- Esta interface está vacía (lo cual resulta un poco sorprendente)

- Este es un comportamiento definido por el api de Java distinto al comportamiento habitual (y por ello resulta un tanto confuso).

- Lo correcto para implementar el método clone es implementar la interface y sobreescribir el método clone (a pesar de que implementar la interface no obliga a ello).


¿Por qué no se obliga a sobreescribir el método clone? Esto son detalles del lenguaje que habría que preguntarle a los creadores del lenguaje. Supongo que debe haber algún motivo pero como programadores ya sabemos lo necesario aunque nos quede la duda del por qué han hecho esto así.

Saludos

RaGa

  • Moderador Global
  • Intermedio
  • *******
  • APR2.COM
  • Mensajes: 234
    • Ver Perfil
Excelente Alex! Había que recurrir al "libro sagrado" de Oracle. Muchas gracias por ser tan claro y explicativo en el desarrollo del tema.

Mi preocupación residía en que tal vez había una razón (por mi desconocida) que explicara ese comportamiento de la interface. Y que tal vez ese mismo comportamiento (la de declarar interfaces del API sin métodos abstractos) se replicaría en otras interfaces por alguna razón que debiera conocer.

Ahora, leyendo la publicación doc de Oracle y tu desarrollo, damos cuenta de que es algo de excepción.
Si bien, no sabemos el "por qué", tranquiliza que la documentación nos aclare: cómo utilizar el método, que nos explicite que no declara el método, que es impredecible el resultado de utilizar el método clone() sin implementar la interface Clonable(),  etc.  etc.
En este caso, más importante de los "por qué", es que esté bien documentada por Oracle el comportamiento de la interface.

Un saludo Alex!  :)

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".