2009-03-10 16 views
7

Sto lavorando con un codice che aggiunge un nodo figlio al suo genitore nel costruttore del figlio. Il codice simile a questa:Procedura consigliata: aggiungere un nodo figlio a un genitore nel costruttore figlio o no?

Classe:

class Node1 { 
    public Node1(Node1 parent, String name) { 
    if(parent != null) { 
     parent.add(this); 
    } 
    this.parent = parent; 
    } 

    private void add(Node1 child) { 
    children.add(child); 
    } 
} 

Usage:

Node1 parent = new Node1(null, "parent"); 
Node1 child1 = new Node1(parent, "child1"); 
Node1 child2 = new Node1(parent, "child2"); 

Implementando questo modo l'utente della Classe Node1 non deve aggiungere esplicitamente il nodo figlio (meno codice) al suo genitore e hai garantito che un nodo figlio ha un genitore.

io personalmente non avrei scritto così, ma più simile al seguente:

class Node2 { 
    public Node2(String name) { 
    } 

    public void add(Node2 child) { 
    children.add(child); 
    child.setParent(this); 
    } 
} 

Node2 parent = new Node2("parent"); 
Node2 child1 = new Node2("child1"); 
parent.add(child1); 
Node2 child2 = new Node2("child2"); 
parent.add(child2); 

Quindi la mia domanda è, è una buona idea per la sua attuazione, come mostrato nella classe Node1 o ci sono qualsiasi obiezioni a farlo in questo modo? O non c'è nessuna argomentazione sul perché uno sia migliore dell'altro?

risposta

11

Personalmente non mi piace il primo esempio perché si sta aggiungendo un nodo che non è ancora "pronto" (come il costruttore non ha terminato l'esecuzione). Nella maggior parte dei casi funzionerà bene, ma in casi estremi è possibile avere bug che sono piuttosto difficili da trovare.

+0

+1: Più o meno quello che avrei detto. –

+0

Questo è un buon punto, è meglio non usarlo in un costruttore. –

1

Penso che entrambe le implementazioni siano ok.

La domanda è più come userete questa classe: creerete prima un elenco di nodi e poi inizierete ad aggiungere le loro relazioni o lo farete in modo ordinato, come nell'esempio?

La seconda soluzione offre maggiore flessibilità, anche se si desidera utilizzare Node1 come superclasse, non si è vincolati alla firma del costruttore.

2

Vorrei utilizzare il secondo caso in quanto poi potrò aggiungere i bambini in seguito, ma non solo nel costruttore.

0

Se si ottiene il nodo dalla classe TreeNode, si ottiene automaticamente la seconda implementazione del proprio. Puoi aggiungere il tuo treenode "personalizzato" alla classe Treeview normale.

1

Non mi piace il primo caso: l'oggetto genitore viene magicamente modificato solo dopo essere passato: devi leggere codice o documenti per capire che questo sta accadendo. Il solo passaggio del genitore implica solo che il bambino conosce il genitore - non che il bambino venga aggiunto anche all'elenco interno del genitore.

Il secondo esempio è migliore. Si potrebbe anche restituire il bambino dalla operazione 'add' per consentire il funzionamento concatenamento come:

Node2 child = parent.add(new Node2()); 
1

vedo alcun motivo per cui non combinare i due approcci per comodità:

class Node1 { 
    public Node1(String name, Node1 parent = null) { 
    this.name = name; 
    // etc., do initialization 

    if(parent != null) 
     parent.add(this); 
    } 

    private void add(Node1 child) { 
    child.setParent(this); 
    children.add(child); 
    } 
} 

noti che setParent () dovrebbe generare un'eccezione quando il bambino ha già il suo set genitore o rimuoverlo correttamente dall'elenco figlio dell'ex genitore.

0

In primo luogo il cattivo nel vostro primo campione è: se (genitore! = Null) { è necessario questo controllo perché si dovrebbe avere la possibilità di creare radice di albero, ma a due stati parametro sembra brutto.

Anche il tuo campione non va bene perché fa azioni implicite (aggiungendo figlio al genitore passato).

0

Preferirei l'implementazione n. 1 solo quando è assolutamente essenziale avere un nodo genitore con un nodo figlio. In questo caso, è del tutto possibile che il codice client ometti la chiamata a Node1.add (figlio Nodo1) che porta a errori successivi.

Preferirei implementazione # 2 altrimenti perché è più chiaro di avere un utilizzo come

Node1 parent = new Node1(); 
Node1 child = new Node1(); 
parent.add(child); 
Problemi correlati