Domanda

Sto cercando di implementare un metodo clone() su un DoubleLinkedList. Ora, il problema è che la sua attuazione da "la convenzione" è molto più fastidioso di una semplice creazione di un nuovo DoubleLinkedList e lo riempie di tutti gli elementi della mia DoubleLinkedList corrente.

C'è qualche inconveniente non sto vedendo quando farlo?

Ecco il mio approccio attuale:

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

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

    return dll;
}

Ecco che cosa sarebbe dalla convenzione:

@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());
    }
}
È stato utile?

Soluzione

Come si punta in modo corretto, la convenzione è quello di sempre super.clone() chiamata all'inizio di un'implementazione di clone(). Dalla documentazione API su Object#clone() :

Per convenzione, l'oggetto restituito dovrebbe essere ottenute chiamando super.clone. Se una classe e tutte le sue superclassi (tranne Object) obbediscono questa convenzione, sarà il caso che x.clone (). GetClass () == x.getClass ().

Il primo tentativo (senza l'utilizzo di super.clone()) ha il seguente problema:

Supponiamo che io sono

class IntDoubleLinkedList extends DoubleLinkedList<Integer> implements Cloneable

(e che IntDoubleLinkedList non si preoccupa di esclusione clone()) e ho eseguito il seguente codice:

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

Che cosa accadrà? Il metodo clone di tuo verrà eseguito DoubleLinkedList, che, se non passa attraverso super.clone (), restituisce un'istanza di DoubleLinkedList che a sua volta non può essere colato a un IntDoubleLinkedList. Un ClassCastException saranno gettati!

Così come super.clone() risolvere questo problema? Beh, se tutti bastone alla convenzione di chiamare super.clone() in un metodo clone sovresposta, Object.clone() finirà per essere chiamato, e questa implementazione sarà creare un'istanza di un tipo corretto (IntDoubleLinkedList in questo caso)!

Altri suggerimenti

Come altri hanno già spiegato, se si sta andando ad esclusione clone si dovrebbe obbedire il suo contratto.

Se ti piace il modo in cui attualmente si dispone di esso, basta fare DoubleLinkedList non Cloneable e girare l'implementazione in un costruttore di copia o di metodo factory statico. Un metodo factory statica ha il vantaggio di fornire un po 'di tipo inferenza per gli argomenti di tipo generico, troppo.

P.S. LinkedList è una lista doppiamente collegata.

Se lo si fa con la creazione di una nuova lista e l'aggiunta di tutti gli elementi dalla sorgente, se poi fare qualcosa di simile:

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 sarà "nuovo valore" in entrambe le liste (lo stesso viceversa, se si modifica in L1, appariranno i cambiamenti in L2). Il modo corretto sarebbe quello di realtà clonare ogni elemento e aggiungere il clone al fine di garantire le liste sono indipendenti. Prendere atto che questo succede solo se si cambia proprietà degli elementi, non se si aggiunge, spostare, cancellarli dalla lista.

Modifica:. Appena si rese conto che dal momento che è una lista collegata, gli elementi successiva / precedente sono proprietà dell'elemento, quindi, anche l'aggiunta, l'eliminazione, interesserà sia la lista

Il motivo "convenzione" è chiamare super.clone() è assicurare che il tipo finale dell'oggetto clonato corrispondente all'oggetto che viene clonato. Per esempio se si un'istanza per il proprio nuovo DoubleLinkedList nel metodo clone(), bene che è bello per ora, ma in seguito, se una sottoclasse non riesce a sovrascrivere clone() finirà restituire un clone che è un DoubleLinkedList invece della sua propria classe. (Sarà anche non riescono a clonare i suoi campi aggiuntivi, se del caso, probabilmente! Quindi non ci sono problemi più grandi.)

In questo senso, il metodo convenzionale è preferito, ed è davvero goffa.

Entrambe le implementazioni, tuttavia, hanno un problema simile: non sei profondo copiare le strutture di dati. Il clone è soltanto un poliziotto poco profonda. Questo probabilmente non è quello che l'aspetta chiamanti. Si avrebbe bisogno di passare attraverso e sostituire ogni valore nel DoubleLinkedList con un clone del valore, e allo stesso modo per gli altri campi non primitive.

In questo senso, il metodo convenzionale sta per dare il risultato sbagliato qui! Avete bisogno di una terza via. Il tuo primo metodo probabilmente solo di opere, se non che è necessario aggiungere element.clone() per esempio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top