基 class 可以包含对其子 class 之一的引用吗?

Is it ok for a base class to contain a reference to one of its subclasses?

我写了下面的 classes 来创建一个树层次结构,但是由于所有节点 classes 都包含一个 ParentNode 类型的父节点,我想移动它进入基础 class 所以我不必为所有节点类型重写任何与父节点相关的代码。因此,虽然它显然 有效 ,但在 NodeBase-class 中拥有类型 ParentNode 的字段是否会被视为不好的做法,如果那么,解决这个问题的"correct"方法是什么?

public abstract class NodeBase{
    /*Various general methods and properties*/
}
public class ParentNode : NodeBase{
    public readonly ParentNode Parent;
    public readonly List<NodeBase> Children;

    /*Methods etc related to parent nodes*/
}
public class LeafNode : NodeBase{
    public readonly ParentNode Parent;

    /*Methods etc related to leaf nodes*/
}

我不能只将 public readonly NodeBase Parent 放在 NodeBase-class 中,因为 NodeBase 没有 Children-列表,并且将 Children 放在那里,会导致 LeafNodes 也有该列表。

虽然我不认为这是不好的做法,但它会向我表明我设计了错误。

一般来说,在超级 class 中保留对子 class 的引用没有任何意义。

在这种情况下,我不明白为什么您需要为叶节点和父节点设置单独的 class。所有节点都可以有子节点和父节点。成为叶节点只是没有子节点的结果,任何只影响叶节点的方法都可以只检查列表的计数以确认不存在子节点。就像任何 RootNode 检查都会查看父节点一样。

这个模式用的很频繁,没什么问题。

乍一看,这似乎有点像循环依赖,但实际上并没有什么问题。因此,当您需要(想要)对特殊类型的派生节点的引用时,您可以并且应该对其进行精确建模。比使用更通用的 NodeBase Parent {get; set;} 然后将其与类型转换和额外检查一起使用要好得多,也更安全。

而且很常见,例如在 XObject class:

class XObject
{
   public XElement Parent { get; }
   public XDocument Document { get; }
}

class XElement  : XObject { ... }   // with a few classes 
class XDocument : XObject { ... }   //    in between