clone () solo parzialmente fattibile; come reagire?

0

Supponiamo di avere una gerarchia di classi la cui classe base B richiede un metodo clone() da definire nelle sue derivazioni. Anche se questo funziona perfettamente per la maggior parte di essi, esiste questa derivazione X che contiene un riferimento facoltativo a una risorsa / oggetto che può essere referenziato da un'istanza di X . Mentre il resto di X può essere clonato senza problemi, questo riferimento dovrebbe essere impostato su null / nil / nullptr.

Qual è il modo corretto di gestire questa situazione?

  • X::clone() potrebbe lanciare un UncloneableException . Anche se questo sarebbe corretto, non è soddisfacente.
  • Imposta il riferimento a null / nil / nullptr e non ne noti alcuno. L'utente di X deve conoscere X s "particolarità".
  • Richiedi derivazioni di B per definire B::nearestClone() : l'utente di B deve sapere che il valore restituito potrebbe non essere un clone 1: 1.
  • Qualcos'altro?
posta hllnll 21.08.2014 - 19:30
fonte

3 risposte

1

Non specifichi la lingua che stai usando, ma suggerirei che un approccio sarebbe avere la classe base che dovrebbe avere un protected metodo cloneBase , e quindi per ogni classe che potrebbe supportare la clonazione avere un derivato concreto sigillato che implementa un'interfaccia di clonazione tipicamente tipicamente covariante, con se stesso come parametro di tipo generico. Può essere utile che questa interfaccia includa anche un metodo che le implementazioni useranno per restituire se stessi, digitato in base al parametro generico.

Se AnimalBase non avrebbe difficoltà a supportare la clonazione, ma alcune classi derivate potrebbero avere oggetti non clonabili, quindi Animal dovrebbe essere una classe sigillata che deriva da AnimalBase e implementa ICloneable<Animal> . Se BirdBase deriva da animale, Bird sarebbe un derivato di ciò che implementa ICloneable<Bird> . Se Phoenix deriva da Bird ma non supporta la clonazione, né esso né alcun derivato implementeranno alcuna interfaccia ICloneable .

Utilizzando questo approccio, il codice che ha bisogno di qualcosa che è clonabile e deriva da AnimalBase potrebbe accettare un parametro di tipo ICloneable<AnimalBase> ; un tipo di questo tipo potrebbe accettare Animal o Bird , anche se questi tipi non sono correlati. Il codice che deve utilizzare ICloneable<AnimalBase> come AnimalBase potrebbe utilizzare il suo membro Self .

In alternativa, si potrebbe implementare una proprietà% / metodo IsCloneable e quindi avere un metodo Clone che è garantito funzionare solo se IsCloneable restituisce true. Un simile approccio non fornirebbe un modo per indicare a un tipo di compilazione che aveva bisogno di qualcosa che può essere clonato, ma eviterebbe la necessità di tipi "foglia" extra sigillati. Anche se c'è un certo vantaggio che i metodi esprimano i loro requisiti attraverso i loro parametri, c'è anche il vantaggio di evitare la creazione di tipi altrimenti inutili.

    
risposta data 21.08.2014 - 20:11
fonte
1

Sotto i vincoli della domanda, avrei un'interfaccia come questa (pseudocodice):

public interface Cloneable<T> {
  boolean isCloneable();
  T clone();
}

Il metodo isCloneable() restituirebbe true se l'oggetto corrente può essere clonato, mentre il metodo clone() eseguirà il clone effettivo. Questo è un trucco kludgy per il fatto che una sottoclasse potrebbe non essere clonabile nonostante l'implementazione dell'interfaccia Cloneable . Se il tuo linguaggio di programmazione fornisce già un'interfaccia Cloneable , potrebbe essere necessario aggiungerne uno per farlo funzionare.

In realtà, questo intero esercizio serve a dimostrare che un'interfaccia Cloneable è una cattiva idea. Mette un vincolo su qualsiasi classe che implementa direttamente o indirettamente l'interfaccia, e potenzialmente qualsiasi classe contenuta in Cloneable oggetti .

La tua domanda presuppone che la clonazione debba essere supportata. Tuttavia, il modo ideale di copiare un oggetto è non di avere un'interfaccia Cloneable , ma di infornare l'idea di "copiare" direttamente in una classe senza usando il tipo sistema per definire ciò che è e non è clonabile. Questo è fuori dalla portata della tua domanda, ma potrebbe valere la pena esplorare come un esercizio separato (e forse una domanda successiva).

    
risposta data 21.08.2014 - 22:19
fonte
0

Sembra una particolare istanza di X è la "alpha" X ed è, in effetti, un singleton. Rompe alcuni principi di progettazione ma potrebbe essere comunque ragionevole.

Il rigoroso approccio purista è che alphaX non è clonabile, né persistibile, ecc. in modo che nessuno possa rompere il contratto singleton. Questo è in realtà difficile e ha generato molti articoli e libri. Le tue opzioni sono di rendere tutte le X non clonabili, o solo di alphaX per generare un'eccezione. L'utente può sapere se la sua particolare X è l'alfa?

Tuttavia, se questo è più simile ai nodi di un albero in cui esiste un nodo radice speciale, ma il clone ha ancora un senso (se cloni genitore e figli è una buona domanda) potresti clonare ma impostare quel riferimento su null .

Quindi, "dipende". Mi dispiace che questo non è definitivo. : -)

    
risposta data 21.08.2014 - 22:03
fonte

Leggi altre domande sui tag