Best practice: add node child to parent in child constructor or not?

I am working with some code that adds a child of a node to its parent in a child constructor. The code looks something like this:

Grade:

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

Using:

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

By implementing it this way, the user of the Node1 class Node1 not explicitly add the node's child (less code) to his parent, and you have guaranteed that the node's child has a parent.

I personally would not write it like this, but it looks more like the following:

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

So my question is: is it good to implement it, as shown in the Node1 class, or are there any objections to this? Or are there no arguments in favor of why one is better than the other?

+7
oop
source share
8 answers

I personally do not like the first example because you add a Node that is not "ready" yet (since the constructor has not finished executing). In most cases, it will work fine, but in extreme cases, you may have errors that are quite difficult to find.

+11
source share

I would use the second case, since later I can add children later, but not only in the constructor.

+2
source share

I think both implementations are fine.

The question is how you will use this class: first you create a list of nodes, and then you start adding their relations or will you do it in an orderly manner, as in your example?

The second solution offers more flexibility, also if you ever want to use Node1 as a superclass, you are not tied to the constructor signature.

+1
source share

I don’t like the first case - the parent object is magically modified, just passing it on - you need to read the code or documents to understand that this is happening. Just passing a parent implies that the child knows the parent, not that the child is also added to the parent's internal list.

The second example is better. You can also return the child from the add operation to enable the chain of operations, for example:

 Node2 child = parent.add(new Node2()); 
+1
source share

I see no reason why not combine the two approaches for convenience:

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

Note that setParent () must either throw an exception when the child already has its own parent set, or it should be removed from the previous parent child list correctly.

+1
source share

If you derive Node from the TreeNode class, you will automatically get a second implementation. You can add your custom treenode to the regular Treeview class.

0
source share

First, the bad in the first example: if (parent! = Null) { this check is necessary because you should be able to create the root of the tree, but the two-state parameter looks ugly.

Also, at first, your sample is not very good, because it performs implicit actions (adding a child to the parent).

0
source share

I would prefer implementation # 1 only when it is absolutely necessary to have a parent node with a child node. In this case, the client code may well omit the call to Node1.add (Node1 child), which will lead to errors later.

I would prefer implementation # 2 otherwise, because it is clearer to have a use like

 Node1 parent = new Node1(); Node1 child = new Node1(); parent.add(child); 
0
source share

All Articles