最佳实践:在子构造函数中是否将子节点添加到父节点?

时间:2009-03-10 12:34:38

标签: oop

我正在使用一些代码,在子代的构造函数中将子节点添加到它的父节点。代码看起来像这样:

类别:

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

用法:

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

通过这种方式实现它,类Node1的用户不必显式地将子节点(更少的代码)添加到它的父节点,并且您已经保证子节点具有父节点。

我个人不会这样写,但更像是以下内容:

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

所以我的问题是,按照Node1类所示实现它是一个好主意,还是有任何反对意见?或者没有争论为什么一个人比另一个好?

8 个答案:

答案 0 :(得分:11)

我个人不喜欢第一个例子,因为你正在添加一个尚未“准备好”的节点(因为构造函数没有完成执行)。在大多数情况下它会正常工作,但在极端情况下你可能会遇到很难找到的错误。

答案 1 :(得分:2)

我会使用第二种情况,因为我以后可以添加子项,但不仅仅是在构造函数中。

答案 2 :(得分:1)

我认为两种实现都没问题。

问题是你将如何使用这个类:你会先创建一个节点列表然后开始添加他们的关系,还是会以有序的方式进行,比如你的例子?

第二种解决方案提供了更大的灵活性,如果您想将Node1用作超类,则不必绑定构造函数签名。

答案 3 :(得分:1)

我不喜欢第一种情况 - 父对象只是通过传入进行神奇修改 - 你必须阅读代码或文档才能意识到这种情况正在发生。只传入父级只意味着孩子知道父级 - 而不是孩子也被添加到父级的内部列表中。

第二个例子更好。您还可以从“添加”操作返回子项以允许操作链接,如:

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

答案 4 :(得分:1)

为了方便起见,我认为没有理由不将这两种方法结合起来:

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

请注意,setParent()应该在子项已经设置父项时抛出异常,或者从父项的子列表中正确删除它。

答案 5 :(得分:0)

如果从TreeNode类派生Node,那么您将自动获得第二个实现。您可以将“自定义”treenode添加到常规Treeview类中。

答案 6 :(得分:0)

首先,您的第一个示例中的错误是: if(parent!= null){ 需要进行此检查,因为您应该有机会创建树的根,但是双状态参数看起来很丑。

首先,您的样本不好,因为执行隐式操作(将子项添加到传递的父项)。

答案 7 :(得分:0)

只有当父节点具有子节点绝对必要时,我才更喜欢实现#1。在这种情况下,客户端代码很可能省略对Node1.add(Node1子节点)的调用,导致稍后出现错误。

我更喜欢实现#2,否则因为使用

这样的用法更清楚
Node1 parent = new Node1();
Node1 child = new Node1();
parent.add(child);