Frage

Ich versuche eine implementieren clone() Methode auf a DoubleLinkedList. Das Problem ist nun, dass die Implementierung durch "die Konvention" viel mehr problematisch ist, als nur eine neue zu erstellen DoubleLinkedList und füllen Sie es mit allen Elementen meiner aktuellen DoublelinkedList.

Gibt es unpraktische, ich sehe nicht, wenn ich das mache?

Hier ist mein aktueller Ansatz:

@Override
public DoubleLinkedList<T> clone() {
    DoubleLinkedList<T> dll = new DoubleLinkedList<T>();

    for (T element : dll) {
        dll.add(element);
    }

    return dll;
}

Hier ist, was es nach der Konvention sein würde:

@Override
public DoubleLinkedList<T> clone() {
    try {
        DoubleLinkedList<T> dll = (DoubleLinkedList<T>)super.clone();
        //kinda complex code to copy elements
        return dll;
    } catch (CloneNotSupportedException e) {
        throw new InternalError(e.toString());
    }
}
War es hilfreich?

Lösung

Wie Sie richtig betonen, wird die Konvention immer anrufen super.clone() Zu Beginn einer Umsetzung von clone(). Von dem API -Dokumente auf Object#clone():

Nach Übereinkommen sollte das zurückgegebene Objekt durch Calling Super.clone erhalten werden. Wenn eine Klasse und alle Superklassen (außer Objekt) dieser Konvention befolgen, ist es der Fall, dass X.clone (). GetClass () == X.getClass ().

Ihr erster Versuch (ohne zu verwenden super.clone()) hat das folgende Problem:

Angenommen, ich habe

class IntDoubleLinkedList extends DoubleLinkedList<Integer> implements Cloneable

(und das IntDoubleLinkedList Macht sich nicht die Mühe zu überschreiben clone()) und ich führen den folgenden Code aus:

IntDoubleLinkedList idll = new IntDoubleLinkedList();
IntDoubleLinkedList idll2 = (IntDoubleLinkedList) idll.clone();

Was wird passieren? Die Klonmethode von dein DoubleLinkedList wird ausgeführt, was, wenn es nicht über Super.clone () geht, eine Instanz von zurückgibt DoubleLinkedList was wiederum nicht zu einem gegossen werden kann IntDoubleLinkedList. EIN ClassCastException wird geworfen!

Wie geht es also super.clone() dieses Problem lösen? Nun, wenn sich alle an der Kongress des Berufungskonvents halten super.clone() in einer Überschreibungsklonmethode, Object.clone() wird irgendwann aufgerufen, und diese Implementierung erzeugt eine Instanz eines ordnungsgemäßen Typs (IntDoubleLinkedList in diesem Fall)!

Andere Tipps

Wie andere erklärt haben, wenn Sie außer Kraft setzen clone Sie sollten seinen Vertrag befolgen.

Wenn Ihnen die Art und Weise gefällt, wie Sie es derzeit haben, machen Sie einfach DoubleLinkedList nicht Cloneable und verwandeln Sie Ihre Implementierung in eine Kopiekonstruktor oder eine statische Fabrikmethode. Eine statische Fabrikmethode hat den zusätzlichen Vorteil, dass auch Argumente für generische Typ -Argumente ein bisschen Typ involviert werden.

Ps LinkedList ist eine doppelt verknüpfte Liste.

Wenn Sie dies tun, indem Sie eine neue Liste erstellen und alle Elemente aus der Quelle hinzufügen, dann tun Sie so etwas wie:

DoubleLinkedList<Foo> l1 = new DoubleLinkedList<Foo>();
l1.add (new Foo(params));
DoubleLinkedList<Foo> l2 = l1.clone();
Foo foo = l2.get(0);
foo.setProperty("new Value");

Foo.Property wird in beiden Listen "neuer Wert" sein (das gleiche umgekehrt; wenn Sie ihn in L1 ändern, werden Änderungen in L2 angezeigt). Der richtige Weg wäre, jedes Element und den Klon hinzuzufügen, um sicherzustellen, dass die Listen unabhängig sind. Beachten Sie, dass dies nur geschieht, wenn Sie die Eigenschaften der Elemente ändern, nicht, wenn Sie hinzufügen, verschieben, sie aus der Liste löschen.

Bearbeiten: Ich habe gerade erkannt, dass die nächsten/früheren Elemente, da es sich um eine verknüpfte Liste handelt, Eigenschaften des Elements sind. Sogar das Hinzufügen, Löschen, wirkt sich auf beide Liste aus.

Der Grund, warum die "Übereinkommen" anrufen super.clone() Es ist, dass der ultimative Typ des geklonten Objekts dem klonierten Objekt entspricht. Zum Beispiel, wenn Sie Ihr eigenes Neues instanziieren DoubleLinkedList in dem clone() Methode, das ist fürs Erste schön, aber später, wenn eine Unterklasse nicht überschreibt clone() Es wird am Ende einen Klon zurückgeben, der a ist DoubleLinkedList anstelle einer eigenen Klasse. (Wahrscheinlich gibt es auch keine größeren Probleme.)

In diesem Sinne wird die konventionelle Methode bevorzugt und tatsächlich klobig.

Beide Implementierungen haben jedoch ein ähnliches Problem: Sie können die Datenstrukturen nicht tief ausschöpfen. Der Klon ist nur ein flacher Polizist. Dies ist wahrscheinlich nicht das, was der Anrufer erwartet. Sie müssten jeden Wert in der DoubleLinkedList mit einem Klon des Wertes und ebenfalls für andere nicht primitive Felder.

In diesem Sinne wird die konventionelle Methode hier das falsche Ergebnis erzielen! Sie brauchen einen dritten Weg. Ihre erste Methode funktioniert wahrscheinlich gerade so, dass Sie hinzufügen müssen element.clone() zum Beispiel.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top