2009-07-06 13 views
10

Qualcuno ha delle best practice o convenzioni di denominazione suggerite o stabilite per costruttori di copie/metodi di produzione ecc. In Java? In particolare, dire che ho una classe Thing e voglio un metodo da qualche parte che restituisca un nuovo Thing con lo stesso valore di un Thing passato (o come istanza se si tratta di un metodo di istanza). Avresti questo come costruttore o un metodo factory factory o un metodo di istanza? Come lo chiameresti?Se non si clona in Java, cosa si fa e come si chiama?

Come per il titolo, voglio evitare clone() e Cloneable.

+0

Perché vuoi evitare clone() e Cloneable? –

+0

@Thomas Owens, vedere qui: http://www.artima.com/intv/bloch13.html – Yishai

+0

alle risposte che indicano copia costruttore come soluzione: il costruttore di copie non gestisce correttamente tutti i casi. Ad esempio quando non conosci la classe concreta (ma puoi ancora utilizzare il costruttore di copie all'interno del tuo metodo clone/copy/whateveryoucallit). –

risposta

3

Lo chiamerei metodo di copia o costruttore di copie (a seconda dei casi). Se fosse un metodo statico, allora lo chiamerei fabbrica.

In termini di cosa fare, l'opzione di vita più flessibile e lunga è un costruttore di copie. Questo dà alle sottoclassi la possibilità di copiare se stessi proprio come il genitore.

2

farei un costruttore

... 
public Thing(Thing copyFrom) 
{ 
    attr1 = copyFrom.attr1; 
    attr2 = copyFrom.attr2; 
    //etc... 
} 

poi quando si desidera clonare esso

Thing copy = new Thing(copy from me); 
0

Hai alcune opzioni, implementare Cloneable, aggiungere un costruttore di copia, ma il mio modo preferito consiste nell'utilizzare un metodo (statico o istanza) con un nome descrittivo dell'operazione di copia, una copia profonda o superficiale, ecc.

15

Efficace suggerimento Java ripara una delle seguenti operazioni:

  1. un costruttore di copia (come notato da altri):

    Articolo pubblico (voce Voce)

  2. un metodo di copia di fabbrica:

    Articolo public static newInstance (Elemento articolo)

(Inoltre, nessuna copia per immutables)

La differenza principale è che con # 1 si sceglie la classe effettiva del risultato e con # 2 l'implementatore può restituire una sottoclasse. La semantica della classe può guidarti verso quale è la migliore.

0

Utilizzare immutable data structures. L'unica ragione per cui ritieni di aver bisogno di clone() è che stai mormorando gli oggetti sul posto. Smettila. Pensa a come puoi:

  • Rendi le tue lezioni definitive.
  • Rendi i campi finali e privati ​​dei tuoi corsi.

Per esempio, ecco un "setter" per un oggetto 3D vettore di immutabile:

public Vector3D setX(double x) { 
    return new Vector3D(x, this.y, this.z); 
} 

quindi credo che quello che sto dicendo è ... Io uso costruttori di copia invece di mutazione, e io basta nominarli in base all'attributo che voglio modificare.

0

Un'altra opzione è quella di implementare il metodo di copia nel fonte oggetto, ad esempio:

interface Has3DCoords { 
    void setLocation(double x, double y, double z); 

    void copyCoordsTo(Has3DCoords dest); 
} 

Si potrebbe quindi implementare la copia con un pezzo di codice come:

class Thing implements Has3DCoords { 
    private Point3D loc; 
    // ... 

    void setLocation(double x, double y, double z) { 
     loc.setLocation(x, y, z); 
     // or: loc = new Point3D(x, y, z); 
    } 

    void copyCoordsTo(Has3DCoords dest) { 
     loc.copyCoordsTo(dest); 
     // or: dest.setLocation(loc.getX(), loc.getY(), loc.getZ()); 
    } 

    OtherThing createOtherThing() { 
     OtherThing result = new OtherThing(); 
     this.copyCoordsTo(result); 
     return result; 
    } 
} 

Questo può essere utile se:

  • Non ha senso clonare l'intero oggetto
  • C'è un gruppo di proprietà correlate che spesso vengono copiati come una sola unità
  • non si vuole esporre loc come una proprietà di Thing
  • Il numero di proprietà è di grandi dimensioni (o ci sono molti di questi gruppi) in modo un costruttore che ha richiesto tutti loro come parametri sarebbe poco maneggevole.
0

Questo non è l'approccio più bello per la copia di oggetti, ma ciò che segue è a volte utile se si desidera eseguire una copia completadi un Serializable oggetto . Ciò evita di dover scrivere dei costruttori di copie, implementare Cloneable o scrivere classi factory.

ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(bos); 

//Serializes the input object 
oos.writeObject(input); 

ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray()); 
ObjectInputStream ois = new ObjectInputStream(bais); 

//Copy of the input object 
Object output = ois.readObject(); 

Non dimenticare di gestire le eccezioni e chiudere bene i flussi.