Obejecte Clonen

Status
Nicht offen für weitere Antworten.

Mariem

Mitglied
Hallo aller Seits,

Ich habe gelesen dass "Nicht alle Objecte kopiert werden können".
Deshalb stelle ich mir die Frage: Was es bedeutet, wenn ein Object Cloneable ist. Und Wozu dient die Methode Clone().

Mit Freundlichen Grüßen
 
Zuletzt bearbeitet:

Landei

Top Contributor
Klonen gehört zu den ziemlich verkorksten Sachen. Object implementiert die Methode clone, ist aber nicht Cloneable (und wirft entsprechend eine Exception, wenn du es versuchst). Wenn du eine Klasse "klonbar" machen willst, implementierst du einfach das Interface Cloneable (was keine Methoden hat, ein sogenanntes "Marker-Interface"). Jetzt kommt es darauf an, ob du eine "tiefe" oder eine "flache" Kopie haben willst. Für eine flache Kopie reicht die Standard-Implementierung von clone(), du bist also fertig. Wenn aber z.B. das Original und die Kopie ein Date-Objekt oder so enthalten, können sie die gegenseitigen Änderung in diesem Date "sehen", d.h. das Date-Objekt ist bei beiden Objekten dasselbe. Für eine "tiefe" Kopie, die auch referenzierte Objekte klont, musst du die clone() Methode überschreiben. In der Regel rufst du dann zuerst super.clone() auf und machst dann deine Kopien von den referenzierten Objekten. Details siehe Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 10.2 Object ist die Mutter aller Klassen

Ich schlage dir vor, lieber einen Copy-Konstruktor anzulegen, der ist wesentlich übersichtlicher und weniger fehleranfällig:

Java:
class X {
  int y;
  Date z;
  //"normaler" Konstruktor
  class X(int x, Date z) {
    this.x = x; 
    this.z = new Date(z.getTime()); //defensives kopieren
  }
  //Copy-Konstruktor
  class X(X x) {
    this(x.y, x.z);
  } 

}

//um zu "klonen":
X xCopy = new X(xOriginal);
 
Zuletzt bearbeitet:

Noctarius

Top Contributor
Er meinte natürlich ^^:

Java:
class X {
  int y;
  Date z;
  //"normaler" Konstruktor
  public X(int x, Date z) {
    this.x = x; this.z = new Date(z.getDate());
  }
  //Copy-Konstruktor
  public X(X x) {
    this(x.y, x.z);
  } 
 
}
 
//um zu "klonen":
X xCopy = new X(xOriginal);
 

Mariem

Mitglied
Danke Landei und Noctarius für die schnelle Antwort, ich kann es nicht umgehen denn meiner Aufgabe ist es ein paar Klassen so zu ändern das die Cloneable sind und das ich auch die Methode Clone() benutze :)
Ich habe immer noch die gleiche Frage Was es bedeutet, wenn ein Object Cloneable ist? und warum sind nicht alle Objecte Cloneable?
Mir fellt jetzt noch einer andere Frage: Ich habe mehrere Klassen "rectangle", Linie und "Circle" die unter Klassen sind von der Klasse "Shape" : ) jetzt kommt die Frage:
Könnte man durch den Entwurf der Klassenhierarchie erzwingen, dass jemand, der eine Klasse von
Shape ableitet, ebenfalls die Methode clone() implementiert?
 

Noctarius

Top Contributor
Könnte man durch den Entwurf der Klassenhierarchie erzwingen, dass jemand, der eine Klasse von Shape ableitet, ebenfalls die Methode clone() implementiert?

Shape muss das Interface Cloneable implementieren, als abstract gekennzeichnet sein und dann wird die Methode clone(), sofern nicht in der abstrakten Klasse implementiert, von den Subklassen als implementiert erwartet.
 

Mariem

Mitglied
Danke Noctarius, das habe ich verstanden.
MarcB ich habe dieser Information unter : Implementing the clone() Method - Part 2
gelesen:
. Da man nicht davon ausgehen kann, dass alle Elmente auch kopierbar sind, ist man beim clone diesen Kompromiss eingegangen.

Nicht alle Objekte können kopiert

Deshalb stelle Ich mir die Frage: Was bedeutet es, wenn ein Object cloneable ist? und wann ist es nicht?
 

Landei

Top Contributor
Wenn ein Object "cloneable" ist, kannst du es klonen (wenn alles richtig implementiert ist), sonst eben nicht (der Aufruf wird mit einer CloneNotSupportedException oder so quittiert). Was sollte es sonst bedeuten? Und ein Objekt ist dann und genau dann "cloneable", wenn es das interface Cloneable implementiert. Ich denke, du denkst hier viel zu kompliziert.

Die Implementierung dieses Konzepts in Java ist und bleibt verkorkst. Object muss clone zur Verfügung stellen, damit über Compiler-Magie oder so in den Unterklassen mit dem Aufruf super.clone() ein geklontes Basisobjekt zur Verfügung steht, das dann (meist) Grundlage für alles Weitere darstellt. Trotzdem soll die Klasse Object konzeptionell nicht klonbar sein. Damit werden Spracheigenschaften, Compilerverhalten und ein Interface der Standardbibliothek irgendwie miteinander vermantscht. Eben unsauber und verkorkst, also nicht wundern, sondern nur staunen...
 
Zuletzt bearbeitet:

Noctarius

Top Contributor
Und ein Objekt ist dann und genau dann "cloneable", wenn es das interface Cloneable implementiert.

Dem würde ich nur halb beipflichten. Ein Objekt ist nur dann sauber cloneable wenn es sich per DeepCopy kopieren lässt. Das setzt gewisse Anforderungen an die verwendeten Datentypen / Klassen. Quasi die selben, welche auch für das Serializable gelten.

Sind diese Anforderungen erfüllt lässt es sich "recht schön" mit einer Kombination auf Cloneable Interface und CopyConstructor lösen.

Java:
public class Foo implements Cloneable {
    public Foo() {
        // Public constructors for instancing the objects
    }

    private Foo(Foo foo) {
        // standard copy constructor
    }


    public Foo clone() {
        return new Foo(this);
    }
}


Aber allgemein hat Landei recht, das Cloneable Konzept ist irgendwie nie richtig durchdacht gewesen.
 

Landei

Top Contributor
Habe doch schon X-mal geschrieben "wenn es richtig implementiert ist" und so, und auch schon tiefe und flache Kopie erklärt. Und wie kommst du darauf, dass nur die tiefe Kopie die "saubere" ist? In vielen Fällen ist das Kopieren unnötig (oder sogar unmöglich, wenn man z.B. ein Singleton hat)

Übrigens: Dein Ansatz ist zwar OO-technisch sehr hübsch, geht aber an der Hauptaufgabe von Cloneables vorbei: clone() wird in der Regel implementiert, um sich die Kosten der "normalen" Objekterzeugung zu sparen (was insbesondere bei sehr vielen, aber kleinen Objekten ins Gewicht fällt), ist also ein Trick zur Performance-Optimierung. Ansonsten sehe ich keinen guten Grund, clone() statt einem Copy-Constructor zu verwenden.
 
Zuletzt bearbeitet:

Noctarius

Top Contributor
Weil ich z.B. wenn ich einen String im Clone änder, diese Änderung nicht!!!! im Original haben will oder halt andersherum und das ist nur das simple Beispiel. Die Definition von Cloneable ist ein geklontes, eigenständiges Objekt und keinen neuen Referenzholder auf alte Referenzen zu erzeugen. Das widerspricht schon der Annahme was man hinter einem Clone erwartet. Ergo kann ein tiefeskopierbares Objekt das einzige mögliche Konstrukt sein.
 

Landei

Top Contributor
Strings sind immutable, sie sind gerade etwas, das man nicht zu kopieren braucht. Bei einem Array oder einer Liste von Strings sieht es natürlcih wieder anders aus.
 

Noctarius

Top Contributor
Ok Strings waren scheiss Beispiel, stimmt :D Nennen wir es char-Array *hust* *gg* *radier und überpinselt*
 

Landei

Top Contributor
Aber selbst wenn das Referenz-Objekt veränderlich ist, heißt das noch lange nicht, dass es kopiert werden muss. Die Frage ist, ob das Hauptobjekt das referenzierte Objekt "besitzt" (oder "dafür verantwortlich ist") oder nicht. Wenn ich mir z.B. dynamisch einen Referenz auf einen Service oder so beschafft habe, ist es natürlich Blödsinn, den zu klonen. Oder es haben sich z.B. Listener beim Hauptobjekt registriert, die wirst du auch kaum klonen wollen, oder?
 

Noctarius

Top Contributor
Das ist wohl richtig. Solche Klassen würde ich aber auch nicht als Cloneable markieren. Cloneable können aus meiner Sicht nur reine Datenobjekte z.B. Beans (nach Java Meinung und nicht wie in Spring wo quasi alles eine Bean ist) oder DTOs sein.

Mir würde es vom Sinn her widerstreben ein Objekt mit Businesslogik clone-bar zu machen.

Mag aber persöhnliche Ansicht sein *schulter zuck*
 

Landei

Top Contributor
Aber selbst bei reinen Datenobjekten kann es sinnvoll sein, z.B. Listener registrieren zu lassen (etwa PropertyChangeListener).
 

Noctarius

Top Contributor
Du gibst auch nie auf, aber ja ok das sehe ich ein. Man mag eventuell nicht alles clonen. Aber in diesem Falle ist das Field für mich dann auch kein Datenfeld.

Abgesehen davon würde ich in diesem Falle eine Ableitung des DTO erstellen um die Logik zu verkapseln und dann nach unten durchreichen.
 

Landei

Top Contributor
Du gibst auch nie auf,...
Neben den von Larry Wall genannten drei Tugenden eines Programmieres gibt es noch eine vierte: Sturheit

Sturheit ist wichtig...
- um einem Nutzer zu erklären, dass das perpetuum mobile, das er haben will, nicht funktionieren wird
- um auf einer präzisen Problembeschreibung zu beharren (nicht nur um zu sehen, ob man selber, sondern auch der Anforderer verstanden hat, um was es geht)
- um einen Bug wirklich zu erschlagen, und nicht nur ein Pflästerchen draufzukleben
- um seinen Arbeitgeber zu überzeugen, endlich die richtigen Werkzeuge bereitzustellen
- um ein schlechtes Design nicht durchgehen zu lassen, nur weil es "funktioniert"
- um sich nicht darauf zu verlassen, dass etwas funktionieren wird, sondern auf einem Test zu bestehen
... und bei vielen anderen Gelegenheiten
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben