2009-03-10 13 views
7

Estoy trabajando con un código que agrega un nodo secundario a su padre en el constructor del niño. El código es como la siguiente:Práctica recomendada: ¿Agregar nodo hijo a un elemento primario en el constructor hijo o no?

Clase:

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); 
    } 
} 

Uso:

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

Mediante la implementación de esta manera el usuario de la clase Node1 no tiene que añadir explícitamente el nodo hijo (menos código) a su padre y tiene garantizado que un nodo hijo tiene un padre.

yo personalmente no lo hubiera escrito como éste, sino más bien como la siguiente:

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); 

Así que mi pregunta es, ¿es una buena idea para ponerlo en práctica, como se muestra en la clase Node1 o hay objeciones para hacerlo de esa manera? ¿O no hay ningún argumento de por qué uno es mejor que el otro?

Respuesta

11

Personalmente, no me gusta el primer ejemplo porque está agregando un Nodo que aún no está "listo" (ya que el constructor no terminó de ejecutarse). En la mayoría de los casos funcionará bien, pero en casos extremos puede tener errores que son bastante difíciles de encontrar.

+0

+1: Bastante más de lo que habría dicho. –

+0

Este es un buen punto, es mejor no usar esto en un constructor. –

1

Creo que ambas implementaciones están bien.

La pregunta es más acerca de cómo va a utilizar esta clase: ¿creará primero una lista de nodos y luego comenzará a agregar sus relaciones o lo hará de forma ordenada, como en su ejemplo?

La segunda solución ofrece más flexibilidad, incluso si alguna vez quiere utilizar Node1 como una superclase, no está obligado a la firma del constructor.

2

Usaría el segundo caso, ya que luego podré agregar hijos más adelante, pero no solo en el constructor.

0

Si deriva Nodo de la clase TreeNode, automáticamente obtiene la segunda implementación de la suya. Puede agregar su treenode "personalizado" a la clase normal Treeview.

1

No me gusta el primer caso - el objeto principal se modifica mágicamente con solo pasarlo - tiene que leer el código o los documentos para darse cuenta de que esto está sucediendo. El solo hecho de pasar al padre solo implica que el niño conoce al padre, y no que el niño también se agregue a la lista interna del padre.

El segundo ejemplo es mejor. También podría regresar al niño de la operación de 'añadir' para permitir la operación de encadenamiento como:

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

veo ninguna razón por qué no combinar los dos enfoques para mayor comodidad:

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); 
    } 
} 

Tenga en cuenta que setParent () debería arrojar una excepción cuando el niño ya tiene su grupo primario o eliminarse correctamente de la lista secundaria del padre anterior.

0

En primer lugar el mal en su primera muestra es: si (padre! = Null) { es necesaria esta comprobación, ya que debe tener la oportunidad de crear la raíz del árbol, pero de dos estados parámetro se ve feo.

También primero su muestra no es buena porque realiza acciones implícitas (agregando un hijo al padre pasado).

0

Preferiría la implementación n. ° 1 solo cuando es absolutamente esencial tener un nodo primario con un nodo secundario. En este caso, es bastante posible que el código del cliente omita la llamada a Node1.add (hijo Node1) que conduce a errores más adelante.

preferiría aplicación # 2 de otro modo, ya que es más claro que tener un uso como

Node1 parent = new Node1(); 
Node1 child = new Node1(); 
parent.add(child); 
Cuestiones relacionadas