Frage

Ich habe das Buch „Effective Java“ gelesen und verstehe keinen Absatz, in dem die Clonable-Schnittstelle erklärt wird.Kann mir jemand diesen Absatz erklären:

... Programmierer gehen davon aus, dass sie eine Klasse erweitern und aufrufen super.clone Aus der Unterklasse wird das zurückgegebene Objekt eine Instanz der Unterklasse sein.Die einzige Möglichkeit, wie eine Superklasse diese Funktionalität liefern kann super.clone.Wenn eine Klonmethode ein von einem Konstruktor erstellte Objekt zurückgibt, hat sie die falsche Klasse.

Danke.

War es hilfreich?

Lösung

Das sollte ich zunächst einmal anmerken clone an und für sich ist kaputt, und das ist ein Kopierkonstruktor, wie Sheep(Sheep cloneMe) ist eine weitaus elegantere Redewendung als clone, unter Berücksichtigung der Cloneable Vertrag ist sehr schwach.Das wissen Sie wahrscheinlich bereits, da Sie das Buch lesen, aber es lohnt sich, es hier einzufügen.

Wie auch immer, um die Frage zu beantworten:

Object.clone() erstellt ein Objekt desselben Typs wie das Objekt, für das es aufgerufen wurde.Aus diesem Grund wird dringend empfohlen, bis zu „kaskadieren“. Object um das Ergebnis zu erzielen, das Sie zurückgeben möchten.Wenn jemand beschließt, diese Konvention nicht zu befolgen, erhalten Sie am Ende ein Objekt vom Typ der Klasse, die gegen die Konvention verstoßen hat, was eine Vielzahl von Problemen verursachen wird.

Zur Veranschaulichung: Ich habe eine Klasse wie diese

class Sheep implements Cloneable {

    Sheep(String name)...

    public Object clone() {
        return new Sheep(this.name); // bad, doesn't cascade up to Object
    }
}

class WoolySheep extends Sheep {

    public Object clone() {
        return super.clone();
    }
}

Plötzlich, wenn ich es tue

WoolySheep dolly = new WoolySheep("Dolly");
WoolySheep clone = (WoolySheep)(dolly.clone()); // error

Ich bekomme eine Ausnahme wegen dem, was ich zurückbekomme dolly.clone() ist ein Sheep, kein WoolySheep.

Andere Tipps

Ich stimme nicht mit @ Corsisis Antwort zu.Seit Java5.0.Java unterstützt den kovariantigen Rückkehrtyp Daher sollte die korrekte Implementierung für Klon () sein: generasacodicetagpre.

Der empfohlene alternative Kopierkonstruktor unterstützt keinen Polymorphismus.Erwägen Sie das folgende Beispiel (der Copy Constructor kann nicht tun): generasacodicetagpre.

class A {
    protected Object clone() {
        return new A();
    }
}

class B extends A implements Cloneable {
    public Object clone() {
        return super.clone();
    }
}

Hier, A hat eine ungültige Implementierung von clone weil dies eine Ausnahme auslösen wird:

B obj = (B)(new B()).clone();

Stattdessen, A.clone() muss anrufen super.clone() anstelle eines Konstruktors. Object.clone() generiert dann ein neues Objekt vom Laufzeittyp anstelle des Kompilierzeittyps.

Alle Felder werden dann auf dieses neue Objekt geklont.Es wäre verlockend, einen Konstruktor zu verwenden, wenn Sie bereits einen haben, der alle Ihre Felder initialisiert (wie einen Kopierkonstruktor), aber das würde zu falschem Verhalten für alle Unterklassen führen.

Wenn die Klasse ist final, dann spielt es keine Rolle, da es keine Unterklassen haben kann.

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