2013-08-09 10 views
5
  1. Dovrebbero i copie difensive sempre essere fatte per riferimenti a oggetti di oggetti mutabili passati a costruttori?Come profondo dovrebbe copiare costruttori ottengono

  2. Se sì, allora quanto "profondo" dovrei andare a fare copie. Nel seguente esempio dovrei creare copie profonde all'interno dei costruttori di copia di tutte le classi coinvolte?

Esempio:

class Graph { 
    AdjacencyList; 
    public Graph(Graph graph) { 
     this.list = graph.list; // shallow copy 
     OR 
     this.list = ArrayCopy(graph.list); // deep copy 
    } 
} 

class DFS implements GraphAlgo { 
    Graph g 
    DFS(Graph g) { 
    this.g = g; // shallow copy 
    OR 
    this.g = new Graph(graph) // deep copy 
    } 

    DFS(Algo algo) { 
    this.g = algo.g; // shallow copy 
    OR 
    this.g = new Graph(algo.g); // deep copy 
    } 

} 

class Algo { 
    GraphAlgo galgo 

    Algo (GraphAlgo dfsalgo) { 
     galgo = dfsalgo // shallow copy 
     OR 
     galgo = new DFSAlgo(dfsalgo); // deep copy 
    } 
} 

3 .. E se qualche classe dimentica di implementare copia completa? Significa che non avrò mai un oggetto protetto in profondità? Un modo per prevenire questo?

+0

Non osare! Fare riferimento a http://stackoverflow.com/q/2156120/1065197 –

+1

Un'obbligazione per "preferire l'immutabilità", quindi non è necessario preoccuparsi di questo genere di cose. –

risposta

5

Dovresti essere sulla difensiva?
Solo se è necessario.

Quanto profondo dovresti andare?
Per quanto necessario.

Suono banale? Bene, la risposta di base a questo tipo di domande è "fai il minimo necessario per fornire la funzionalità richiesta".

2

generale: Non fare copie di difesa a meno che non vi fidate il codice chiamante.

Do: Documentare l'interfaccia e dire che non è consentito modificare nulla che passano se ciò causerà un problema.

A volte: Fornire due costruttori. Uno usa l'oggetto. Uno ne fa una copia. Quindi lascia che il chiamante chiami quello che fa una copia quando necessario. Il chiamante può scartare qualsiasi riferimento a quell'oggetto subito dopo aver chiamato il costruttore. In tal caso, non è necessaria alcuna copia.

Algo (GraphAlgo dfsalgo, boolean doCopy) { 
    if (doCopy) { 
     galgo = new DFSAlgo(dfsalgo); // deep copy 
    } else { 
     galgo = dfsalgo // shallow copy 
    } 
} 

Se si considera attendibile il codice chiamante: ignorare la questione. Aspettatevi di fare copie di qualsiasi cosa che non sta per scartare (dal suo punto di vista) prima di chiamare il vostro codice.

Paranoia non significa che non sono fuori per prenderti. Ma non significa che siano entrambi.