8

我有一个类别/文件树结构。类别和文件都可以有父级,因此我从具有 Parent 属性的公共基类派生它们。由于所有父节点显然总是类别(文件不能是父节点),因此将节点的 Parent 属性设置为 CategoryNode 类型似乎是有意义的。

基类引用派生类是不好的形式吗?如果是这样,为什么?如果是这样,有什么更好的方法来构建这个?

class Node {
    public CategoryNode Parent {get; set;}
}

class File : Node {
    ...
}

class CategoryNode : Node {
    ...
}
4

4 回答 4

7

你可以做...

interface IParent {
    ...
}

class Node {
    public IParent Parent {get; set;}
}

class File : Node {
    ...
}

class CategoryNode : Node, IParent {
    ...
}

这样,您不需要在基类中引用派生对象,此外,您可以更灵活地实际成为父对象,以防您在以后获得其他对象类型。此外,任何仅与父级相关的功能都可以在该接口中声明。

于 2012-07-03T07:40:05.530 回答
4

如果该属性Parent实际上是所有后代的公共属性并且始终属于 CategoryNode 类型,则不是问题。从语义上讲,它是正确的,从技术上讲,只要您留在同一个库中,我认为它也是正确的(以避免循环引用)。

当您编写这样的代码时,这可能是一个问题:

// BAD CODE
if(myProp is subclassA) 
{ ... 
} 
else if (myProp is syubclassB) 
{ ...
}

这段代码很糟糕,因为您失去了继承的优势。

即使在 .Net Framework 中也有这样的结构。我想到的第一个例子是XObject.Parent属性。

XElement 继承了 XObject,并且 XObject 发布了 XElement 类型的属性。和你的片段一样。

于 2012-07-03T07:36:41.370 回答
1

基类不应该知道谁派生自它。

如果你有这样的情况,你可能不想要继承。您应该只使用某种形式的耦合。

File 和 CategoryNode 在您的情况下应该包含一个 Node 成员。

于 2012-07-03T07:36:15.347 回答
1

其他选项将是更改类层次结构以使 CategoryNode 成为根类 (a),或将属性类型更改为 Node (b)。

这两种可能性都不好: (a) 文件将具有 CategoryNode 不需要的所有功能。(b) 它将隐藏对象类型(始终为 CategoryNode)。这可能会导致代码中其他地方的无效转换错误。例如,如果您忘记了总有一个 CategoryNode 实例。

考虑到这一点,我相信当前的代码是可以的。

于 2012-07-03T07:38:32.587 回答