web-dev-qa-db-fra.com

Pourquoi la méthode clone () est-elle protégée dans Java.lang.Object?

Quelle est la raison spécifique pour laquelle clone() est défini comme protégé dans Java.lang.Object?

99
Alex N.

Le fait que le clone soit protégé est extrêmement douteux - tout comme le fait que la méthode clone n'est pas déclarée dans l'interface Cloneable.

Cela rend la méthode assez inutile pour prendre des copies de données car vous ne pouvez pas le dire:

if(a instanceof Cloneable) {
    copy = ((Cloneable) a).clone();
}

Je pense que le design de Cloneable est maintenant largement considéré comme une erreur (citation ci-dessous). Je souhaiterais normalement pouvoir implémenter une interface Cloneable mais ne pas forcément rendre l'interface Cloneable (similaire à l'utilisation de Serializable). Cela ne peut pas être fait sans réflexion:

ISomething i = ...
if (i instanceof Cloneable) {
   //DAMN! I Need to know about ISomethingImpl! Unless...
   copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}

Citation de Effective Java:
"L’interface Cloneable était conçue comme une interface de mixage permettant aux objets d’annoncer qu’ils autorisent le clonage. Malheureusement, elle ne sert pas cet objectif ... C’est une utilisation très atypique d’interfaces qui ne doit pas être émulée ... pour que l’implémentation de l’interface ait un effet sur une classe, elle et toutes ses super-classes doivent obéir à un protocole assez complexe, inapplicable et en grande partie non documenté "

97
oxbow_lakes

L'interface Clonable n'est qu'un marqueur indiquant que la classe peut prendre en charge le clonage. La méthode est protégée parce que vous ne devriez pas l'appeler sur un objet, vous pouvez (et devriez) la remplacer en tant que publique. 

Du soleil:

Dans la classe Object, la méthode clone () est déclarée protégée. Si tout ce que vous faites est d'implémenter Cloneable, seuls les sous-classes et les membres du même package pourront appeler clone () sur l'objet. Pour permettre à une classe de n'importe quel package d'accéder à la méthode clone (), vous devez la remplacer et la déclarer publique, comme indiqué ci-dessous. (Lorsque vous substituez une méthode, vous pouvez la rendre moins privée, mais pas plus privée. Ici, la méthode protected clone () dans Object est remplacée comme méthode publique.)

24
Bill K

clone est protégé parce que c'est quelque chose qui devrait être remplacé afin qu'il soit spécifique à la classe actuelle. S'il serait possible de créer une méthode publique clone qui clonerait n'importe quel objet, cela ne serait pas aussi efficace qu'une méthode écrite spécifiquement pour la classe qui en a besoin.

7
Andrew Hare

La méthode Clone ne peut pas être utilisée directement sur un objet. C'est pourquoi elle est censée être remplacée par la sous-classe.

Bien sûr, cela pourrait être public et créer une exception appropriée lorsque le clonage n’est pas possible, mais je pense que ce serait trompeur.

La manière dont le clone est implémenté à l’heure actuelle vous fait penser à la raison pour laquelle vous voulez utiliser le clone et à la manière dont vous voulez que votre objet soit cloné.

4
Silfverstrom

Il est protégé parce que l'implémentation par défaut effectue une copie peu profonde membre par membre de tous les champs (y compris les champs privés), contournant le constructeur . Ce n'est pas quelque chose qu'un objet peut être conçu pour gérer en premier lieu (par exemple, il peut garder une trace des instances d'objet créées dans une liste partagée, ou quelque chose de similaire).

Pour la même raison, l'implémentation par défaut de clone() lancera si l'objet sur lequel il est appelé n'implémente pas Cloneable. C'est une opération potentiellement dangereuse avec des conséquences de grande portée, et par conséquent, l'auteur du cours doit explicitement s'inscrire.

2
Pavel Minaev

Du javadoc de clonable.

* By convention, classes that implement this interface (cloneable) should override 
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link Java.lang.Object#clone()} for details on overriding this
* method.

* Note that this interface does <i>not</i> contain the <tt>clone</tt> 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.

Vous pouvez donc appeler clone sur chaque objet, mais cela ne vous donne généralement pas les résultats souhaités ni une exception. Mais n’est encouragé que si vous implémentez clonable. 

2
Janusz

IMHO c'est aussi simple que cela:

  • #clone ne doit pas être appelé sur des objets non clonables, il n'est donc pas rendu public
  • #clone doit être appelé par les sous-classes ob Object qui implémentent Cloneable pour obtenir la copie superficielle de la bonne classe

Quelle est la bonne portée pour les méthodes pouvant être appelées par des sous-classes, mais pas par d'autres classes?

C'est protected.

Les classes implémentant Cloneable rendront bien sûr cette méthode publique afin qu'elle puisse être appelée à partir d'autres classes.

2
Michaela Elschner

La méthode Clone () a une vérification interne «instance de Cloneable ou non». C’est ainsi que l’équipe Java pourrait penser qu’elle restreindra l’utilisation non conforme de la méthode clone (). Puisque objet est la classe parente de toutes les sous-classes, la méthode Clone () peut donc être utilisée par toutes les classes si nous n'avons pas la vérification ci-dessus de 'instance de Cloneable'. C’est la raison pour laquelle l’équipe Java aurait pu penser à limiter l’utilisation abusive de clone () en vérifiant la méthode clone () «est-ce une instance de Cloneable»?.

Par conséquent, quelle que soit la classe implémentée, cloneable peut utiliser la méthode clone () de la classe Object. 

De plus, puisqu'il est protégé, il n'est disponible que pour les sous-classes qui implémentent une interface clonable. Si nous voulons le rendre public, cette méthode doit être remplacée par la sous-classe avec sa propre implémentation.

0
SARIKA