Warum ist die Methode clone () nur für Klassen verfügbar, die die Cloneable-Schnittstelle implementieren? [Duplikat]

9

Ich weiß, dass clone() eine geschützte Methode ist, aber "protected" bedeutet, dass sie für alle Unterklassen einer bestimmten Klasse zugänglich ist.

Jede Java-Klasse ist eine Unterklasse von Object . Was ist der Grund für die geschützte Methode hier?

Und warum können wir clone() nur für Klassen aufrufen, die das Interface Cloneable implementieren? Ich kann nicht verstehen, wie es sich mit der Tatsache verbindet, dass clone() in Object als geschützt erklärt wird.

    
Don_Quijote 14.08.2013, 18:58
quelle

6 Antworten

8

Die clone () -Methode des Objekts ist ziemlich speziell, da sie immer eine Instanz der aktuellen Klasse zurückgibt, in der alle Felder kopiert sind (sogar final). Ich denke nicht, dass es möglich ist, dies mit einfachem Java-Code zu reproduzieren, nicht einmal mit Reflektion.

Aus diesem Grund muss es für alle Klassen verfügbar gemacht werden, aber da es nicht standardmäßig von außen aufgerufen werden kann, weil Sie nicht möchten, dass alles klonbar ist, muss es geschützt werden.

Als zusätzliche Überprüfung überprüft clone , dass die Klasse Cloneable implementiert, um sicherzustellen, dass Sie nicht-klonbare Dateien nicht versehentlich kopieren.

Alles in allem ist das Klonen etwas kaputt, weil es nicht funktioniert, wenn Sie endgültige Felder tiefkopieren müssen. Ich empfehle Ihnen, das Kopieren von Instanzen manuell zu implementieren, indem Sie diesem Muster folgen.

%Vor%     
Cephalopod 14.08.2013, 19:08
quelle
3

Die Standardimplementierung von Object.clone() ist die einzige Möglichkeit (außer vielleicht Reflection), über die eine Basistyp-Methode in einem Objekt ein neues Objekt desselben Typs erzeugen kann. Andererseits gibt es viele Klassen, bei denen es für eine abgeleitete Klasse unmöglich wäre, eine funktionierende Methode clone zu implementieren, die die Basisklasseninvarianten nicht verletzen würde. Es war erwünscht, dass solche abgeleiteten Klassen nicht clone aufrufen dürfen und ein Objekt erhalten, das möglicherweise nicht verwendbar ist.

Im Nachhinein könnte es richtig gewesen sein, ein System CloneableObject zu definieren, das von Object erbt, das eine geschützte memberwiseclone Methode enthält (das funktioniert wie Object.clone() jetzt tut) und sonst nichts, und alle Klassen, die klonierbar sein werden, erben von diesem als Basistyp. Dieser Typ könnte dann eine spezielle Magie in seiner clone() -Methode verwenden, die für andere Typen nicht verfügbar war. Stattdessen verwendet das System das Vorhandensein der Schnittstelle Cloneable , um zu entscheiden, ob Objekte die Methode clone() auf Basisebene verwenden dürfen. Kein großartiges Design, aber es ist was es ist. Schwer zu sagen, ob das besser oder schlechter als der .NET-Ansatz ist, fast allen abgeleiteten Klassen zu erlauben, MemberwiseClone aufzurufen, ob es eine abgeleitete Klasse geben könnte oder nicht, ohne dass ein zerbrochenes Objekt entsteht.

    
supercat 14.08.2013 19:13
quelle
2

Cloneable ist eine Schnittstelle. Um einen Verweis auf eine abstrakte Basisklasse zu klonen, muss entweder die Basisklasse über eine clone () -Methode verfügen oder einer ihrer Eltern muss über eine öffentlich zugängliche clone () -Methode verfügen. Cloneable fungiert nur als Marker-Schnittstelle.

Siehe:

Ankit Zalani 14.08.2013 19:03
quelle
2

Weil sie es so entworfen haben. Es gibt eine Aussage irgendwo in der Bug Parade, dass die ursprünglichen Gründe für das Design "im Nebel der Zeit verloren sind", aber ich erinnere mich an eine Diskussion von Sun in den 1990ern, dass das Design vier mögliche Verhaltensweisen gab.

Ich kann mich nicht an die Details erinnern: - | Aber Sie können es herausfinden:

  1. Nichts tun. Die Klasse kann nicht geklont werden, und auf die clone() -Methode kann nur mit abgeleiteten Klassen zugegriffen werden.
  2. Implement Cloneable: Class kann geklont werden, aber auf clone() method kann nur mit abgeleiteten Klassen zugegriffen werden.
  3. Implementieren Sie Cloneable und geben Sie Ihre eigene clone() -Methode an: as (2), aber die Möglichkeit besteht, clone() public zu machen und nun auch den korrekten Typ zurückzugeben.
  4. Abgeleitet von einer Klasse, die (2) oder (3) ausführt, implementieren Sie clone() und werfen NotCloneableException: zurück auf 1.

Wenn clone() in die Schnittstelle eingefügt wurde, wäre etwas davon verloren gegangen.

    
EJP 14.08.2013 19:08
quelle
1

Ссылка

  

Eine Klasse implementiert die Cloneable-Schnittstelle, um der Object.clone () -Methode anzuzeigen, dass es für diese Methode zulässig ist, eine Feld-für-Feld-Kopie von Instanzen dieser Klasse zu erstellen.   Das Aufrufen der Clone-Methode von Object für eine Instanz, die die Cloneable-Schnittstelle nicht implementiert, führt dazu, dass die Ausnahme CloneNotSupportedException ausgelöst wird.

     

Per Konvention sollten Klassen, die diese Schnittstelle implementieren, Object.clone (das geschützt ist) mit einer öffentlichen Methode überschreiben. Details zum Überschreiben dieser Methode finden Sie unter Object.clone ().

     

Beachten Sie, dass diese Schnittstelle die Klonmethode nicht enthält. Daher ist es nicht möglich, ein Objekt nur dadurch zu klonen, dass es diese Schnittstelle implementiert. Auch wenn die Clone-Methode reflektiv aufgerufen wird, gibt es keine Garantie, dass sie erfolgreich sein wird.

Kommen Sie zu Ihrer Frage, obwohl das Objekt die geschützte Methode clone Object nicht Cloneable implementiert hat, aber das Objekt, das die Methode clone() heißt, muss Cloneable interface implementieren.

    
quelle
-1

Cloneable ist eine Marker-Schnittstelle . Die clone () -Methode ist nicht durch die Cloneable-Schnittstelle definiert.

Die clone-Methode in der Object-Klasse ist geschützt, um zu verhindern, dass eine Client-Klasse sie aufruft. - Nur Unterklassen können clone aufrufen oder überschreiben, und dies ist ein schlechte Idee .

    
Bill Horvath 14.08.2013 19:12
quelle

Tags und Links